{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Notice**: The `semantica.kg_qa` module is temporarily unavailable and will be reintroduced in a future release. Any quality assessment examples in this notebook are disabled."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Hawksight-AI/semantica/blob/main/cookbook/use_cases/blockchain/02_Transaction_Network_Analysis.ipynb)\n",
    "\n",
    "# Transaction Network Analysis Pipeline\n",
    "\n",
    "## Overview\n",
    "\n",
    "This notebook demonstrates a complete blockchain transaction network analysis pipeline: stream transactions from multiple sources (blockchain APIs, transaction feeds, databases), build temporal transaction knowledge graph, persist to graph database, detect AML patterns, trace fund flows, and generate alerts.\n",
    "\n",
    "\n",
    "**Documentation**: [API Reference](https://semantica.readthedocs.io/use-cases/)\n",
    "\n",
    "### Modules Used (20+)\n",
    "\n",
    "- **Ingestion**: FileIngestor, WebIngestor, FeedIngestor, StreamIngestor, DBIngestor, RepoIngestor, EmailIngestor, MCPIngestor\n",
    "- **Parsing**: JSONParser, StructuredDataParser\n",
    "- **Extraction**: NERExtractor, RelationExtractor, EventDetector, TripleExtractor\n",
    "- **KG**: GraphBuilder, TemporalGraphQuery, TemporalPatternDetector, GraphAnalyzer\n",
    "- **Graph Store**: GraphStore with Neo4j/FalkorDB for persistent blockchain graph\n",
    "- **Analytics**: CentralityCalculator, CommunityDetector, ConnectivityAnalyzer\n",
    "- **Reasoning**: InferenceEngine, RuleManager, ExplanationGenerator\n",
    "- **Quality**: KGQualityAssessor, ConflictDetector\n",
    "- **Export**: JSONExporter, RDFExporter, ReportGenerator\n",
    "- **Visualization**: KGVisualizer, TemporalVisualizer, AnalyticsVisualizer\n",
    "\n",
    "### Pipeline\n",
    "\n",
    "**Real-time Transaction Streams → Parse → Extract Entities (wallets, transactions, addresses) → Build Temporal Transaction KG → Store in Graph DB → Detect Patterns (tumbling, mixing, clustering) → AML Analysis → Generate Alerts → Visualize**\n",
    "\n",
    "## Installation\n",
    "\n",
    "Install Semantica from PyPI:\n",
    "\n",
    "```bash\n",
    "pip install semantica\n",
    "# Or with all optional dependencies:\n",
    "pip install semantica[all]\n",
    "```\n",
    "\n",
    "---\n",
    "\n",
    "## Step 1: Stream Transactions from Multiple Sources\n",
    "\n",
    "Stream blockchain transactions from APIs, feeds, and databases.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.ingest import StreamIngestor, WebIngestor, DBIngestor, FileIngestor\n",
    "from semantica.parse import JSONParser, StructuredDataParser\n",
    "from semantica.semantic_extract import NERExtractor, RelationExtractor, EventDetector, TripleExtractor\n",
    "from semantica.kg import GraphBuilder, TemporalGraphQuery, TemporalPatternDetector, GraphAnalyzer\n",
    "from semantica.kg import CentralityCalculator, CommunityDetector, ConnectivityAnalyzer\n",
    "from semantica.reasoning import InferenceEngine, RuleManager, ExplanationGenerator\n",
    
    "from semantica.conflicts import ConflictDetector\n",
    "from semantica.export import JSONExporter, RDFExporter, ReportGenerator\n",
    "from semantica.visualization import KGVisualizer, TemporalVisualizer, AnalyticsVisualizer\n",
    "import tempfile\n",
    "import os\n",
    "import json\n",
    "from datetime import datetime, timedelta\n",
    "\n",
    "stream_ingestor = StreamIngestor()\n",
    "web_ingestor = WebIngestor()\n",
    "db_ingestor = DBIngestor()\n",
    "file_ingestor = FileIngestor()\n",
    "\n",
    "json_parser = JSONParser()\n",
    "structured_parser = StructuredDataParser()\n",
    "\n",
    "# Real streaming sources for blockchain transactions\n",
    "stream_sources = [\n",
    "    {\n",
    "        \"type\": \"kafka\",\n",
    "        \"topic\": \"blockchain_transactions\",\n",
    "        \"bootstrap_servers\": [\"localhost:9092\"],\n",
    "        \"consumer_config\": {\"group_id\": \"transaction_analysis\"}\n",
    "    },\n",
    "    {\n",
    "        \"type\": \"rabbitmq\",\n",
    "        \"queue\": \"eth_transactions\",\n",
    "        \"connection_url\": \"amqp://user:password@localhost:5672/\"\n",
    "    }\n",
    "]\n",
    "\n",
    "# Real blockchain APIs\n",
    "blockchain_apis = [\n",
    "    \"https://api.etherscan.io/api?module=proxy&action=eth_getBlockByNumber&tag=latest&boolean=true&apikey=YourApiKeyToken\",  # Etherscan API\n",
    "    \"https://blockchain.info/rawblock/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f\",  # Blockchain.com API\n",
    "    \"https://api.coingecko.com/api/v3/coins/ethereum\"  # CoinGecko API\n",
    "]\n",
    "\n",
    "# Real database connection for transaction history\n",
    "db_connection_string = \"postgresql://user:password@localhost:5432/blockchain_db\"\n",
    "db_query = \"SELECT tx_hash, from_address, to_address, value, timestamp, block_number FROM transactions WHERE timestamp > NOW() - INTERVAL '24 hours' ORDER BY timestamp DESC LIMIT 10000\"\n",
    "\n",
    "temp_dir = tempfile.mkdtemp()\n",
    "\n",
    "# Sample transaction data for local ingestion\n",
    "transaction_data_file = os.path.join(temp_dir, \"transactions.json\")\n",
    "transaction_data = [\n",
    "    {\n",
    "        \"tx_hash\": \"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\",\n",
    "        \"from_address\": \"0xabc123def456abc123def456abc123def456abc12\",\n",
    "        \"to_address\": \"0xdef456abc123def456abc123def456abc123def45\",\n",
    "        \"value\": \"1000000000000000000\",\n",
    "        \"timestamp\": (datetime.now() - timedelta(hours=1)).isoformat(),\n",
    "        \"block_number\": 18500000,\n",
    "        \"gas_used\": 21000\n",
    "    },\n",
    "    {\n",
    "        \"tx_hash\": \"0x2345678901bcdef2345678901bcdef2345678901bcdef2345678901bcdef23\",\n",
    "        \"from_address\": \"0xdef456abc123def456abc123def456abc123def45\",\n",
    "        \"to_address\": \"0x7890123456789012345678901234567890123456\",\n",
    "        \"value\": \"500000000000000000\",\n",
    "        \"timestamp\": (datetime.now() - timedelta(hours=2)).isoformat(),\n",
    "        \"block_number\": 18499950,\n",
    "        \"gas_used\": 21000\n",
    "    },\n",
    "    {\n",
    "        \"tx_hash\": \"0x3456789012cdef3456789012cdef3456789012cdef3456789012cdef3456\",\n",
    "        \"from_address\": \"0x7890123456789012345678901234567890123456\",\n",
    "        \"to_address\": \"0xabc123def456abc123def456abc123def456abc12\",\n",
    "        \"value\": \"2000000000000000000\",\n",
    "        \"timestamp\": (datetime.now() - timedelta(hours=3)).isoformat(),\n",
    "        \"block_number\": 18499900,\n",
    "        \"gas_used\": 21000\n",
    "    },\n",
    "    {\n",
    "        \"tx_hash\": \"0x4567890123def4567890123def4567890123def4567890123def4567890123\",\n",
    "        \"from_address\": \"0xabc123def456abc123def456abc123def456abc12\",\n",
    "        \"to_address\": \"0x4567890123456789012345678901234567890123\",\n",
    "        \"value\": \"300000000000000000\",\n",
    "        \"timestamp\": (datetime.now() - timedelta(hours=4)).isoformat(),\n",
    "        \"block_number\": 18499850,\n",
    "        \"gas_used\": 21000\n",
    "    },\n",
    "    {\n",
    "        \"tx_hash\": \"0x5678901234ef5678901234ef5678901234ef5678901234ef5678901234ef56\",\n",
    "        \"from_address\": \"0x4567890123456789012345678901234567890123\",\n",
    "        \"to_address\": \"0x1234567890123456789012345678901234567890\",\n",
    "        \"value\": \"1500000000000000000\",\n",
    "        \"timestamp\": (datetime.now() - timedelta(hours=5)).isoformat(),\n",
    "        \"block_number\": 18499800,\n",
    "        \"gas_used\": 21000\n",
    "    }\n",
    "]\n",
    "\n",
    "with open(transaction_data_file, 'w') as f:\n",
    "    json.dump(transaction_data, f, indent=2)\n",
    "\n",
    "# Ingest from local file\n",
    "file_data = file_ingestor.ingest_file(transaction_data_file)\n",
    "parsed_transactions = structured_parser.parse_json(json.dumps(transaction_data))\n",
    "\n",
    "# Ingest from blockchain APIs (example with public API)\n",
    "web_content = web_ingestor.ingest_url(blockchain_apis[2])  # CoinGecko public API\n",
    "if web_content:\n",
    "    print(f\"  Ingested blockchain API: {blockchain_apis[2]}\")\n",
    "\n",
    "# Database ingestion pattern (would connect to real database)\n",
    "db_data = db_ingestor.export_table(\n",
    "    connection_string=db_connection_string,\n",
    "    table_name=\"transactions\",\n",
    "    limit=10000\n",
    ")\n",
    "print(f\"  Query pattern: {db_query}\")\n",
    "\n",
    "# Streaming ingestion pattern\n",
    "for stream_source in stream_sources:\n",
    "    print(f\"  - {stream_source['type']}: {stream_source.get('topic') or stream_source.get('queue')}\")\n",
    "\n",
    "print(f\"\\n📊 Ingestion Summary:\")\n",
    "print(f\"  Local transactions: {len(transaction_data)}\")\n",
    "print(f\"  Database records: {len(db_data.get('data', [])) if db_data else 0}\")\n",
    "print(f\"  Streaming sources: {len(stream_sources)}\")\n",
    "print(f\"  Web APIs: {len(blockchain_apis)}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 2: Extract Transaction Entities\n",
    "\n",
    "Extract wallets, transactions, and addresses from the ingested data.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ner_extractor = NERExtractor()\n",
    "relation_extractor = RelationExtractor()\n",
    "event_detector = EventDetector()\n",
    "triple_extractor = TripleExtractor()\n",
    "\n",
    "all_transaction_texts = []\n",
    "all_transactions = []\n",
    "\n",
    "# Process parsed transactions\n",
    "if parsed_transactions and isinstance(parsed_transactions, dict):\n",
    "    transactions = parsed_transactions.get(\"data\", transaction_data)\n",
    "    for tx in transactions:\n",
    "        all_transactions.append(tx)\n",
    "        tx_text = f\"Transaction {tx.get('tx_hash', '')} from {tx.get('from_address', '')} to {tx.get('to_address', '')} value {tx.get('value', '')} at {tx.get('timestamp', '')}\"\n",
    "        all_transaction_texts.append(tx_text)\n",
    "\n",
    "# Extract entities\n",
    "all_entities = []\n",
    "all_relationships = []\n",
    "all_events = []\n",
    "all_triples = []\n",
    "\n",
    "for text in all_transaction_texts:\n",
    "    entities = ner_extractor.extract(text)\n",
    "    all_entities.extend(entities)\n",
    "    \n",
    "    relationships = relation_extractor.extract(text, entities)\n",
    "    all_relationships.extend(relationships)\n",
    "    \n",
    "    events = event_detector.detect_events(text)\n",
    "    all_events.extend(events)\n",
    "    \n",
    "    triples = triple_extractor.extract(text)\n",
    "    all_triples.extend(triples)\n",
    "\n",
    "# Build structured entity list\n",
    "transaction_entities = []\n",
    "wallet_entities = []\n",
    "\n",
    "for tx in all_transactions:\n",
    "    tx_entity = {\n",
    "        \"id\": tx.get(\"tx_hash\", \"\"),\n",
    "        \"type\": \"Transaction\",\n",
    "        \"properties\": {\n",
    "            \"from_address\": tx.get(\"from_address\", \"\"),\n",
    "            \"to_address\": tx.get(\"to_address\", \"\"),\n",
    "            \"value\": tx.get(\"value\", \"\"),\n",
    "            \"timestamp\": tx.get(\"timestamp\", \"\"),\n",
    "            \"block_number\": tx.get(\"block_number\", 0),\n",
    "            \"gas_used\": tx.get(\"gas_used\", 0)\n",
    "        }\n",
    "    }\n",
    "    transaction_entities.append(tx_entity)\n",
    "    \n",
    "    # Add wallet entities\n",
    "    from_wallet = {\n",
    "        \"id\": tx.get(\"from_address\", \"\"),\n",
    "        \"type\": \"Wallet\",\n",
    "        \"properties\": {\n",
    "            \"address\": tx.get(\"from_address\", \"\"),\n",
    "            \"role\": \"sender\"\n",
    "        }\n",
    "    }\n",
    "    to_wallet = {\n",
    "        \"id\": tx.get(\"to_address\", \"\"),\n",
    "        \"type\": \"Wallet\",\n",
    "        \"properties\": {\n",
    "            \"address\": tx.get(\"to_address\", \"\"),\n",
    "            \"role\": \"receiver\"\n",
    "        }\n",
    "    }\n",
    "    wallet_entities.append(from_wallet)\n",
    "    wallet_entities.append(to_wallet)\n",
    "\n",
    "# Deduplicate wallets\n",
    "unique_wallets = {}\n",
    "for wallet in wallet_entities:\n",
    "    wallet_id = wallet[\"id\"]\n",
    "    if wallet_id not in unique_wallets:\n",
    "        unique_wallets[wallet_id] = wallet\n",
    "\n",
    "wallet_entities = list(unique_wallets.values())\n",
    "\n",
    "print(f\"Extracted {len(transaction_entities)} transactions\")\n",
    "print(f\"Extracted {len(wallet_entities)} unique wallets\")\n",
    "print(f\"Extracted {len(all_relationships)} relationships\")\n",
    "print(f\"Detected {len(all_events)} events\")\n",
    "print(f\"Extracted {len(all_triples)} triples\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 3: Build Temporal Transaction Knowledge Graph\n",
    "\n",
    "Build a temporal knowledge graph from extracted transactions and wallets.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "builder = GraphBuilder()\n",
    "\n",
    "# Add all entities\n",
    "for wallet in wallet_entities:\n",
    "    builder.add_entity(\n",
    "        entity_id=wallet[\"id\"],\n",
    "        entity_type=wallet[\"type\"],\n",
    "        properties=wallet.get(\"properties\", {})\n",
    "    )\n",
    "\n",
    "for tx in transaction_entities:\n",
    "    builder.add_entity(\n",
    "        entity_id=tx[\"id\"],\n",
    "        entity_type=tx[\"type\"],\n",
    "        properties=tx.get(\"properties\", {})\n",
    "    )\n",
    "\n",
    "# Add relationships\n",
    "relationships = []\n",
    "for tx in transaction_entities:\n",
    "    from_addr = tx[\"properties\"].get(\"from_address\", \"\")\n",
    "    to_addr = tx[\"properties\"].get(\"to_address\", \"\")\n",
    "    tx_hash = tx[\"id\"]\n",
    "    value = tx[\"properties\"].get(\"value\", \"\")\n",
    "    timestamp = tx[\"properties\"].get(\"timestamp\", \"\")\n",
    "    \n",
    "    # Transaction relationship\n",
    "    rel = {\n",
    "        \"source\": from_addr,\n",
    "        \"target\": to_addr,\n",
    "        \"type\": \"transfers_to\",\n",
    "        \"properties\": {\n",
    "            \"transaction\": tx_hash,\n",
    "            \"value\": value,\n",
    "            \"timestamp\": timestamp\n",
    "        }\n",
    "    }\n",
    "    relationships.append(rel)\n",
    "    builder.add_relationship(\n",
    "        source_id=from_addr,\n",
    "        target_id=to_addr,\n",
    "        relationship_type=\"transfers_to\",\n",
    "        properties=rel[\"properties\"]\n",
    "    )\n",
    "    \n",
    "    # Transaction entity relationship\n",
    "    builder.add_relationship(\n",
    "        source_id=from_addr,\n",
    "        target_id=tx_hash,\n",
    "        relationship_type=\"initiates\",\n",
    "        properties={\"timestamp\": timestamp}\n",
    "    )\n",
    "    builder.add_relationship(\n",
    "        source_id=tx_hash,\n",
    "        target_id=to_addr,\n",
    "        relationship_type=\"sends_to\",\n",
    "        properties={\"timestamp\": timestamp}\n",
    "    )\n",
    "\n",
    "knowledge_graph = builder.build()\n",
    "\n",
    "print(f\"Built knowledge graph with {len(knowledge_graph.nodes)} nodes\")\n",
    "print(f\"Built knowledge graph with {len(knowledge_graph.edges)} edges\")\n",
    "print(f\"Added {len(relationships)} transaction relationships\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 4: Persist Transaction Graph to Graph Database\n",
    "\n",
    "Store the transaction knowledge graph in a persistent graph database for AML queries.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from semantica.graph_store import GraphStore\n",
    "\n",
    "# Initialize graph store - FalkorDB is ideal for real-time blockchain analysis\n",
    "# For production: use Neo4j for enterprise features or FalkorDB for ultra-fast queries\n",
    "# graph_store = GraphStore(backend=\"neo4j\", uri=\"bolt://localhost:7687\", user=\"neo4j\", password=\"password\")\n",
    "# graph_store = GraphStore(backend=\"falkordb\", host=\"localhost\", port=6379, graph_name=\"blockchain_graph\")\n",
    "\n",
    "# Option 1: Neo4j (requires Neo4j server running)\n",
    "    graph_store = GraphStore(backend=\"neo4j\", uri=\"bolt://localhost:7687\", user=\"neo4j\", password=\"password\")\n",
    "graph_store.connect()\n",
    "\n",
    "# Store wallet nodes\n",
    "wallet_node_map = {}\n",
    "for wallet in wallet_entities:\n",
    "    node = graph_store.create_node(\n",
    "        labels=[\"Wallet\"],\n",
    "        properties={\n",
    "            \"address\": wallet[\"id\"],\n",
    "            \"role\": wallet[\"properties\"].get(\"role\", \"unknown\")\n",
    "        }\n",
    "    )\n",
    "    wallet_node_map[wallet[\"id\"]] = node.get(\"id\")\n",
    "\n",
    "# Store transaction nodes\n",
    "tx_node_map = {}\n",
    "for tx in transaction_entities:\n",
    "    node = graph_store.create_node(\n",
    "        labels=[\"Transaction\"],\n",
    "        properties={\n",
    "            \"tx_hash\": tx[\"id\"],\n",
    "            \"value\": tx[\"properties\"].get(\"value\", \"0\"),\n",
    "            \"timestamp\": tx[\"properties\"].get(\"timestamp\", \"\"),\n",
    "            \"block_number\": tx[\"properties\"].get(\"block_number\", 0),\n",
    "            \"gas_used\": tx[\"properties\"].get(\"gas_used\", 0)\n",
    "        }\n",
    "    )\n",
    "    tx_node_map[tx[\"id\"]] = node.get(\"id\")\n",
    "\n",
    "# Store relationships\n",
    "for rel in relationships:\n",
    "    if rel[\"source\"] in wallet_node_map and rel[\"target\"] in wallet_node_map:\n",
    "        graph_store.create_relationship(\n",
    "            start_node_id=wallet_node_map[rel[\"source\"]],\n",
    "            end_node_id=wallet_node_map[rel[\"target\"]],\n",
    "            rel_type=\"TRANSFERS_TO\",\n",
    "            properties=rel.get(\"properties\", {})\n",
    "        )\n",
    "\n",
    "\n",
    "# Query for AML analysis using Cypher\n",
    "aml_query = \"\"\"\n",
    "    MATCH (w1:Wallet)-[r:TRANSFERS_TO]->(w2:Wallet)\n",
    "    WITH w1, count(r) as tx_count\n",
    "    WHERE tx_count > 1\n",
    "    RETURN w1.address as wallet, tx_count\n",
    "    ORDER BY tx_count DESC\n",
    "\"\"\"\n",
    "aml_results = graph_store.execute_query(aml_query)\n",
    "\n",
    "temporal_query = TemporalGraphQuery(knowledge_graph)\n",
    "pattern_detector = TemporalPatternDetector()\n",
    "graph_analyzer = GraphAnalyzer()\n",
    "centrality_calculator = CentralityCalculator()\n",
    "community_detector = CommunityDetector()\n",
    "connectivity_analyzer = ConnectivityAnalyzer()\n",
    "\n",
    "# Query transactions in time range\n",
    "start_time = (datetime.now() - timedelta(hours=6)).isoformat()\n",
    "end_time = datetime.now().isoformat()\n",
    "\n",
    "temporal_results = temporal_query.query_time_range(\n",
    "    start_time=start_time,\n",
    "    end_time=end_time,\n",
    "    relationship_types=[\"transfers_to\", \"initiates\", \"sends_to\"]\n",
    ")\n",
    "\n",
    "# Detect temporal patterns\n",
    "temporal_patterns = pattern_detector.detect_temporal_patterns(\n",
    "    knowledge_graph,\n",
    "    relationship_types=[\"transfers_to\"],\n",
    "    time_window_hours=6\n",
    ")\n",
    "\n",
    "# Calculate centrality to find key wallets\n",
    "centrality_result = centrality_calculator.calculate_betweenness_centrality(knowledge_graph)\n",
    "centrality_scores = centrality_result.get('centrality', {})\n",
    "top_central_wallets = sorted(centrality_scores.items(), key=lambda x: x[1], reverse=True)[:10]\n",
    "\n",
    "# Detect communities (clustering)\n",
    "communities_result = community_detector.detect_communities(knowledge_graph, algorithm=\"louvain\")\n",
    "communities = communities_result.get('communities', [])\n",
    "community_count = len(communities) if communities else 0\n",
    "\n",
    "# Analyze connectivity\n",
    "connectivity_results = connectivity_analyzer.analyze_connectivity(knowledge_graph)\n",
    "\n",
    "# AML Pattern Detection using Inference Engine\n",
    "inference_engine = InferenceEngine()\n",
    "rule_manager = RuleManager()\n",
    "\n",
    "# Define AML rules\n",
    "aml_rules = [\n",
    "    {\n",
    "        \"name\": \"tumbling_pattern\",\n",
    "        \"condition\": \"high_transaction_count AND multiple_intermediate_wallets\",\n",
    "        \"action\": \"flag_as_tumbling\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"mixing_pattern\",\n",
    "        \"condition\": \"funds_split_into_multiple_addresses AND rapid_consolidation\",\n",
    "        \"action\": \"flag_as_mixing\"\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"suspicious_flow\",\n",
    "        \"condition\": \"large_value_transfer AND short_time_window\",\n",
    "        \"action\": \"flag_as_suspicious\"\n",
    "    }\n",
    "]\n",
    "\n",
    "for rule in aml_rules:\n",
    "    rule_manager.add_rule(rule[\"name\"], rule[\"condition\"], rule[\"action\"])\n",
    "\n",
    "# Add facts from graph analysis\n",
    "aml_facts = []\n",
    "for wallet_id, centrality in top_central_wallets[:5]:\n",
    "    aml_facts.append({\n",
    "        \"wallet\": wallet_id,\n",
    "        \"centrality\": centrality,\n",
    "        \"high_transaction_count\": True if centrality > 0.1 else False\n",
    "    })\n",
    "\n",
    "# Detect patterns\n",
    "suspicious_patterns = []\n",
    "for wallet_id, centrality in top_central_wallets:\n",
    "    if centrality > 0.15:\n",
    "        suspicious_patterns.append({\n",
    "            \"wallet\": wallet_id,\n",
    "            \"pattern\": \"high_centrality\",\n",
    "            \"risk_score\": min(centrality * 10, 10),\n",
    "            \"description\": f\"Wallet {wallet_id[:10]}... has high betweenness centrality ({centrality:.3f}), indicating potential mixing/tumbling\"\n",
    "        })\n",
    "\n",
    "# Check for rapid transactions (tumbling pattern)\n",
    "wallet_transaction_counts = {}\n",
    "for rel in relationships:\n",
    "    source = rel[\"source\"]\n",
    "    wallet_transaction_counts[source] = wallet_transaction_counts.get(source, 0) + 1\n",
    "\n",
    "for wallet_id, count in wallet_transaction_counts.items():\n",
    "    if count >= 3:\n",
    "        suspicious_patterns.append({\n",
    "            \"wallet\": wallet_id,\n",
    "            \"pattern\": \"rapid_transactions\",\n",
    "            \"risk_score\": min(count * 2, 10),\n",
    "            \"description\": f\"Wallet {wallet_id[:10]}... has {count} outgoing transactions, potential tumbling\"\n",
    "        })\n",
    "\n",
    "print(f\"Detected {len(temporal_patterns)} temporal patterns\")\n",
    "print(f\"Found {community_count} wallet communities\")\n",
    "print(f\"Identified {len(suspicious_patterns)} suspicious patterns\")\n",
    "print(f\"\\nTop 5 Central Wallets:\")\n",
    "for i, (wallet_id, centrality) in enumerate(top_central_wallets[:5], 1):\n",
    "    print(f\"  {i}. {wallet_id[:20]}... (centrality: {centrality:.3f})\")\n",
    "print(f\"\\nSuspicious Patterns Detected:\")\n",
    "for pattern in suspicious_patterns[:5]:\n",
    "    print(f\"  - {pattern['pattern']}: {pattern['wallet'][:20]}... (risk: {pattern['risk_score']:.1f}/10)\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 5: Generate Alerts and Reports\n",
    "\n",
    "Generate AML alerts and comprehensive analysis reports.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "json_exporter = JSONExporter()\n",
    "rdf_exporter = RDFExporter()\n",
    "report_generator = ReportGenerator()\n",
    "kg_quality_assessor = KGQualityAssessor()\n",
    "conflict_detector = ConflictDetector()\n",
    "\n",
    "# Assess graph quality\n",
    "quality_metrics = kg_quality_assessor.assess_quality(knowledge_graph)\n",
    "\n",
    "# Detect conflicts\n",
    "conflicts = conflict_detector.detect_conflicts(knowledge_graph)\n",
    "\n",
    "# Generate alerts\n",
    "alerts = []\n",
    "for pattern in suspicious_patterns:\n",
    "    if pattern[\"risk_score\"] >= 5.0:\n",
    "        alerts.append({\n",
    "            \"alert_id\": f\"AML_{pattern['wallet'][:8]}\",\n",
    "            \"type\": \"AML_SUSPICIOUS_PATTERN\",\n",
    "            \"severity\": \"HIGH\" if pattern[\"risk_score\"] >= 7.0 else \"MEDIUM\",\n",
    "            \"wallet\": pattern[\"wallet\"],\n",
    "            \"pattern\": pattern[\"pattern\"],\n",
    "            \"risk_score\": pattern[\"risk_score\"],\n",
    "            \"description\": pattern[\"description\"],\n",
    "            \"timestamp\": datetime.now().isoformat()\n",
    "        })\n",
    "\n",
    "# Export knowledge graph\n",
    "kg_json = json_exporter.export(knowledge_graph, output_path=os.path.join(temp_dir, \"transaction_kg.json\"))\n",
    "kg_rdf = rdf_exporter.export(knowledge_graph, output_path=os.path.join(temp_dir, \"transaction_kg.rdf\"))\n",
    "\n",
    "# Generate report\n",
    "report_content = f\"\"\"\n",
    "# Blockchain Transaction Network Analysis Report\n",
    "\n",
    "## Executive Summary\n",
    "- Total Transactions Analyzed: {len(transaction_entities)}\n",
    "- Unique Wallets: {len(wallet_entities)}\n",
    "- Suspicious Patterns Detected: {len(suspicious_patterns)}\n",
    "- High-Risk Alerts: {len([a for a in alerts if a['severity'] == 'HIGH'])}\n",
    "\n",
    "## Graph Quality Metrics\n",
    "- Nodes: {quality_metrics.get('node_count', len(knowledge_graph.nodes))}\n",
    "- Edges: {quality_metrics.get('edge_count', len(knowledge_graph.edges))}\n",
    "- Completeness: {quality_metrics.get('completeness', 0):.2%}\n",
    "- Consistency: {quality_metrics.get('consistency', 0):.2%}\n",
    "\n",
    "## Top Suspicious Patterns\n",
    "\"\"\"\n",
    "for i, pattern in enumerate(suspicious_patterns[:10], 1):\n",
    "    report_content += f\"\"\"\n",
    "### {i}. {pattern['pattern'].upper()}\n",
    "- Wallet: {pattern['wallet']}\n",
    "- Risk Score: {pattern['risk_score']:.1f}/10\n",
    "- Description: {pattern['description']}\n",
    "\"\"\"\n",
    "\n",
    "report_content += f\"\"\"\n",
    "## Alerts Generated\n",
    "\"\"\"\n",
    "for alert in alerts:\n",
    "    report_content += f\"\"\"\n",
    "- **{alert['alert_id']}** ({alert['severity']}): {alert['description']}\n",
    "\"\"\"\n",
    "\n",
    "report_path = os.path.join(temp_dir, \"aml_analysis_report.md\")\n",
    "with open(report_path, 'w') as f:\n",
    "    f.write(report_content)\n",
    "\n",
    "print(f\"Generated {len(alerts)} AML alerts\")\n",
    "print(f\"Exported knowledge graph to JSON and RDF\")\n",
    "print(f\"Generated analysis report: {report_path}\")\n",
    "print(f\"\\nQuality Metrics:\")\n",
    "print(f\"  Nodes: {quality_metrics.get('node_count', len(knowledge_graph.nodes))}\")\n",
    "print(f\"  Edges: {quality_metrics.get('edge_count', len(knowledge_graph.edges))}\")\n",
    "print(f\"  Completeness: {quality_metrics.get('completeness', 0):.2%}\")\n",
    "print(f\"  Consistency: {quality_metrics.get('consistency', 0):.2%}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 6: Visualize Transaction Network\n",
    "\n",
    "Visualize the transaction network, patterns, and analytics.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "kg_visualizer = KGVisualizer()\n",
    "temporal_visualizer = TemporalVisualizer()\n",
    "analytics_visualizer = AnalyticsVisualizer()\n",
    "\n",
    "# Visualize knowledge graph\n",
    "kg_viz = kg_visualizer.visualize(\n",
    "    knowledge_graph,\n",
    "    layout=\"force_directed\",\n",
    "    highlight_nodes=[p[\"wallet\"] for p in suspicious_patterns[:5]],\n",
    "    node_size_by=\"centrality\"\n",
    ")\n",
    "\n",
    "# Visualize temporal patterns\n",
    "temporal_viz = temporal_visualizer.visualize(\n",
    "    knowledge_graph,\n",
    "    time_attribute=\"timestamp\",\n",
    "    relationship_types=[\"transfers_to\"]\n",
    ")\n",
    "\n",
    "# Visualize analytics\n",
    "analytics_viz = analytics_visualizer.visualize(\n",
    "    knowledge_graph,\n",
    "    metrics={\n",
    "        \"centrality\": dict(top_central_wallets[:10]),\n",
    "        \"communities\": communities,\n",
    "        \"connectivity\": connectivity_results\n",
    "    }\n",
    ")\n"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
