Spaces:
Running
Running
Clonar https://intel.arkm.com/ porem com UX whiteoff clean barra superior grande de busca -print visualizer (objetivo central do projeto) -Print tracer Abaixo referencia para APIS abertas { "project": "EloOnChain", "description": "A web-based tool. Inspired by ArKham. That allows users to explore blockchain transaction relationships between wallet addresses by visualizing connections as an interactive graph. The tool uses public blockchain APIs to fetch transaction data without requiring authentication or private tokens.", "features": { "address_search": { "enabled": true, "description": "Search bar with autocomplete to input a wallet address (e.g., 0x...). Validates format for Ethereum, Bitcoin, and other supported chains.", "auto_complete": true, "supported_chains": ["Ethereum", "BSC", "Polygon", "Arbitrum", "Bitcoin"] }, "add_additional_addresses": { "enabled": true, "description": "Allow users to manually add more wallet addresses to include in the graph, even if not directly connected on-chain yet.", "method": "Button to 'Add Address' with input field" }, "transaction_history_analysis": { "enabled": true, "description": "Fetch all incoming and outgoing transactions for each address using public, free-tier APIs. No private infrastructure or authentication required.", "api_endpoints": [ { "chain": "Ethereum, BSC, Polygon, Arbitrum, and other EVM chains", "api": "Covalent Free API", "endpoint": "https://api.covalenthq.com/v1/ {chain_id}/address/{address}/transactions_v2/", "example": "https://api.covalenthq.com/v1/1/address/0x1F98431c8aD98523631AE4a59f267346ea31F984/transactions_v2/ ", "api_key_required": false, "note": "Use without key for basic access. Optional key for higher rate limits. Chain IDs: 1 (ETH), 56 (BSC), 137 (Polygon), 42161 (Arbitrum)." }, { "chain": "Ethereum", "api": "Etherscan Public API", "endpoint": "https://api.etherscan.io/api?module=account&action=txlist&address={address}&sort=desc", "example": " https://api.etherscan.io/api?module=account&action=txlist&address=0x1F98431c8aD98523631AE4a59f267346ea31F984&sort=desc", "api_key_required": false, "note": "Works without API key. Free signup increases rate limits. Supports ERC-20 and internal txs via different modules." }, { "chain": "Bitcoin", "api": "Blockchair API", "endpoint": " https://api.blockchair.com/bitcoin/dashboards/address/ {address}", "example": "https://api.blockchair.com/bitcoin/dashboards/address/1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa ", "api_key_required": false, "note": "Returns full transaction history, UTXOs, and balance. No key needed." }, { "chain": "Bitcoin", "api": "Blockchain.com API", "endpoint": "https://blockchain.info/rawaddr/ {address}", "example": "https://blockchain.info/rawaddr/1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa ", "api_key_required": false, "note": "Simple, fast, no authentication. Returns paginated transaction list in JSON." } ] }, "relationship_graph": { "enabled": true, "description": "Visualize addresses as nodes and transactions as directed edges. Show value and frequency of transfers.", "visualization_library": ["Vis.js", "D3.js", "Kumu"], "interactive_features": [ "Zoom and pan", "Click on edge to see transaction details (hash, value, date)", "Color-coded nodes by entity type (if tagged)" ], "data_format": { "nodes": [ { "id": "0xabc...", "label": "Wallet A", "type": "user" }, { "id": "0xdef...", "label": "Uniswap", "type": "contract" } ], "edges": [ { "from": "0xabc...", "to": "0xdef...", "label": "5.2 ETH", "tx_hash": "0x123..." } ] } }, "filters_and_options": { "chain_filter": { "type": "dropdown", "multi_select": true, "options": ["Ethereum", "BSC", "Bitcoin", "Polygon", "Arbitrum"] }, "time_range": { "options": ["Last 24h", "Last 7 days", "Last 30 days", "All time"] }, "min_value_filter": { "unit": "ETH or native token", "description": "Hide transactions below a certain value threshold" } } }, "technical_notes": { "no_private_infrastructure": "This tool does NOT require running blockchain nodes or private APIs. It relies 100% on public, free-tier blockchain APIs.", "rate_limiting": "Respect API rate limits: Covalent (~1 req/sec), Etherscan (~5 req/sec), Blockchair (~10 req/sec). Use caching or delays to stay compliant.", "data_privacy": "No user data is stored. All queries are client-side or ephemeral.", "scalability_limitation": "Optimized for small graphs (1–20 addresses). Not intended for full chain analysis.", "cors_compatibility": "All listed endpoints support CORS and can be called directly from browser-based apps." }, "example_use_case": "User searches for '0x1F98431c8aD98523631AE4a59f267346ea31F984' (Uniswap), adds '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' (USDC) manually, and sees transaction flows between them and other connected wallets." } - Initial Deployment
Browse files- README.md +7 -5
- index.html +592 -19
README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
| 1 |
---
|
| 2 |
+
title: eloonchain
|
| 3 |
+
emoji: 🐳
|
| 4 |
+
colorFrom: pink
|
| 5 |
+
colorTo: blue
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
+
tags:
|
| 9 |
+
- deepsite
|
| 10 |
---
|
| 11 |
|
| 12 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
index.html
CHANGED
|
@@ -1,19 +1,592 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>EloOnChain - Blockchain Relationship Visualizer</title>
|
| 7 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 8 |
+
<script src="https://cdn.jsdelivr.net/npm/vis-network@9.1.2/dist/vis-network.min.js"></script>
|
| 9 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
| 10 |
+
<style>
|
| 11 |
+
.graph-container {
|
| 12 |
+
width: 100%;
|
| 13 |
+
height: 600px;
|
| 14 |
+
border: 1px solid #e5e7eb;
|
| 15 |
+
border-radius: 0.5rem;
|
| 16 |
+
background-color: white;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
.node-contract {
|
| 20 |
+
background-color: #3b82f6 !important;
|
| 21 |
+
color: white !important;
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
.node-wallet {
|
| 25 |
+
background-color: #10b981 !important;
|
| 26 |
+
color: white !important;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
.node-exchange {
|
| 30 |
+
background-color: #f59e0b !important;
|
| 31 |
+
color: white !important;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
.search-dropdown {
|
| 35 |
+
display: none;
|
| 36 |
+
position: absolute;
|
| 37 |
+
width: 100%;
|
| 38 |
+
max-height: 300px;
|
| 39 |
+
overflow-y: auto;
|
| 40 |
+
z-index: 1000;
|
| 41 |
+
background: white;
|
| 42 |
+
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
| 43 |
+
border-radius: 0.375rem;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
.search-dropdown.show {
|
| 47 |
+
display: block;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
.search-dropdown-item {
|
| 51 |
+
padding: 0.75rem 1rem;
|
| 52 |
+
cursor: pointer;
|
| 53 |
+
border-bottom: 1px solid #e5e7eb;
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
.search-dropdown-item:hover {
|
| 57 |
+
background-color: #f3f4f6;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
.api-endpoint {
|
| 61 |
+
font-family: monospace;
|
| 62 |
+
background-color: #f3f4f6;
|
| 63 |
+
padding: 0.25rem 0.5rem;
|
| 64 |
+
border-radius: 0.25rem;
|
| 65 |
+
word-break: break-all;
|
| 66 |
+
}
|
| 67 |
+
</style>
|
| 68 |
+
</head>
|
| 69 |
+
<body class="bg-gray-50 min-h-screen">
|
| 70 |
+
<!-- Header -->
|
| 71 |
+
<header class="bg-white shadow-sm">
|
| 72 |
+
<div class="container mx-auto px-4 py-4">
|
| 73 |
+
<div class="flex justify-between items-center">
|
| 74 |
+
<div class="flex items-center space-x-2">
|
| 75 |
+
<i class="fas fa-link text-blue-500 text-2xl"></i>
|
| 76 |
+
<h1 class="text-xl font-bold text-gray-800">EloOnChain</h1>
|
| 77 |
+
</div>
|
| 78 |
+
<nav class="hidden md:flex space-x-6">
|
| 79 |
+
<a href="#" class="text-gray-600 hover:text-blue-500">Visualizer</a>
|
| 80 |
+
<a href="#" class="text-gray-600 hover:text-blue-500">Tracer</a>
|
| 81 |
+
<a href="#" class="text-gray-600 hover:text-blue-500">API Docs</a>
|
| 82 |
+
<a href="#" class="text-gray-600 hover:text-blue-500">About</a>
|
| 83 |
+
</nav>
|
| 84 |
+
<div class="flex items-center space-x-4">
|
| 85 |
+
<button class="hidden md:block px-4 py-2 text-sm font-medium text-gray-700 hover:text-blue-500">
|
| 86 |
+
<i class="fas fa-user mr-1"></i> Sign In
|
| 87 |
+
</button>
|
| 88 |
+
<button class="px-4 py-2 bg-blue-500 text-white text-sm font-medium rounded-md hover:bg-blue-600">
|
| 89 |
+
<i class="fas fa-rocket mr-1"></i> Get Started
|
| 90 |
+
</button>
|
| 91 |
+
</div>
|
| 92 |
+
</div>
|
| 93 |
+
</div>
|
| 94 |
+
</header>
|
| 95 |
+
|
| 96 |
+
<!-- Main Content -->
|
| 97 |
+
<main class="container mx-auto px-4 py-8">
|
| 98 |
+
<!-- Hero Section with Search -->
|
| 99 |
+
<section class="mb-12">
|
| 100 |
+
<div class="text-center mb-8">
|
| 101 |
+
<h2 class="text-3xl md:text-4xl font-bold text-gray-800 mb-4">Explore Blockchain Relationships</h2>
|
| 102 |
+
<p class="text-lg text-gray-600 max-w-2xl mx-auto">
|
| 103 |
+
Visualize connections between wallet addresses across multiple blockchains.
|
| 104 |
+
No API keys required - powered by public blockchain data.
|
| 105 |
+
</p>
|
| 106 |
+
</div>
|
| 107 |
+
|
| 108 |
+
<!-- Large Search Bar -->
|
| 109 |
+
<div class="max-w-3xl mx-auto relative">
|
| 110 |
+
<div class="relative">
|
| 111 |
+
<input
|
| 112 |
+
type="text"
|
| 113 |
+
id="addressSearch"
|
| 114 |
+
placeholder="Enter a wallet address (e.g., 0x1F984... or 1A1zP1...)"
|
| 115 |
+
class="w-full px-6 py-4 border border-gray-300 rounded-lg shadow-sm focus:ring-blue-500 focus:border-blue-500 text-lg"
|
| 116 |
+
autocomplete="off"
|
| 117 |
+
>
|
| 118 |
+
<button id="searchButton" class="absolute right-2 top-2 px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600">
|
| 119 |
+
<i class="fas fa-search mr-1"></i> Search
|
| 120 |
+
</button>
|
| 121 |
+
</div>
|
| 122 |
+
<div id="searchDropdown" class="search-dropdown mt-1">
|
| 123 |
+
<!-- Dropdown items will be populated by JavaScript -->
|
| 124 |
+
</div>
|
| 125 |
+
</div>
|
| 126 |
+
|
| 127 |
+
<div class="mt-4 text-center text-sm text-gray-500">
|
| 128 |
+
Supported chains: Ethereum, BSC, Polygon, Arbitrum, Bitcoin
|
| 129 |
+
</div>
|
| 130 |
+
</section>
|
| 131 |
+
|
| 132 |
+
<!-- Visualizer Section -->
|
| 133 |
+
<section class="mb-12">
|
| 134 |
+
<div class="flex justify-between items-center mb-4">
|
| 135 |
+
<h3 class="text-xl font-semibold text-gray-800">Transaction Visualizer</h3>
|
| 136 |
+
<div class="flex space-x-2">
|
| 137 |
+
<button id="addAddressBtn" class="px-3 py-1 bg-gray-100 text-gray-700 rounded-md text-sm hover:bg-gray-200">
|
| 138 |
+
<i class="fas fa-plus mr-1"></i> Add Address
|
| 139 |
+
</button>
|
| 140 |
+
<div class="relative">
|
| 141 |
+
<select id="chainFilter" class="appearance-none px-3 py-1 bg-gray-100 text-gray-700 rounded-md text-sm hover:bg-gray-200 pr-8">
|
| 142 |
+
<option>All Chains</option>
|
| 143 |
+
<option>Ethereum</option>
|
| 144 |
+
<option>BSC</option>
|
| 145 |
+
<option>Polygon</option>
|
| 146 |
+
<option>Arbitrum</option>
|
| 147 |
+
<option>Bitcoin</option>
|
| 148 |
+
</select>
|
| 149 |
+
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
|
| 150 |
+
<i class="fas fa-chevron-down text-xs"></i>
|
| 151 |
+
</div>
|
| 152 |
+
</div>
|
| 153 |
+
<div class="relative">
|
| 154 |
+
<select id="timeFilter" class="appearance-none px-3 py-1 bg-gray-100 text-gray-700 rounded-md text-sm hover:bg-gray-200 pr-8">
|
| 155 |
+
<option>All Time</option>
|
| 156 |
+
<option>Last 24h</option>
|
| 157 |
+
<option>Last 7 days</option>
|
| 158 |
+
<option>Last 30 days</option>
|
| 159 |
+
</select>
|
| 160 |
+
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
|
| 161 |
+
<i class="fas fa-chevron-down text-xs"></i>
|
| 162 |
+
</div>
|
| 163 |
+
</div>
|
| 164 |
+
</div>
|
| 165 |
+
</div>
|
| 166 |
+
|
| 167 |
+
<div class="graph-container" id="network"></div>
|
| 168 |
+
|
| 169 |
+
<div class="mt-4 flex justify-between items-center">
|
| 170 |
+
<div class="flex items-center space-x-4">
|
| 171 |
+
<div class="flex items-center">
|
| 172 |
+
<div class="w-3 h-3 rounded-full bg-green-500 mr-1"></div>
|
| 173 |
+
<span class="text-xs text-gray-600">Wallet</span>
|
| 174 |
+
</div>
|
| 175 |
+
<div class="flex items-center">
|
| 176 |
+
<div class="w-3 h-3 rounded-full bg-blue-500 mr-1"></div>
|
| 177 |
+
<span class="text-xs text-gray-600">Contract</span>
|
| 178 |
+
</div>
|
| 179 |
+
<div class="flex items-center">
|
| 180 |
+
<div class="w-3 h-3 rounded-full bg-yellow-500 mr-1"></div>
|
| 181 |
+
<span class="text-xs text-gray-600">Exchange</span>
|
| 182 |
+
</div>
|
| 183 |
+
</div>
|
| 184 |
+
<button id="exportGraph" class="px-3 py-1 bg-gray-100 text-gray-700 rounded-md text-sm hover:bg-gray-200">
|
| 185 |
+
<i class="fas fa-download mr-1"></i> Export
|
| 186 |
+
</button>
|
| 187 |
+
</div>
|
| 188 |
+
</section>
|
| 189 |
+
|
| 190 |
+
<!-- Tracer Section -->
|
| 191 |
+
<section class="mb-12">
|
| 192 |
+
<h3 class="text-xl font-semibold text-gray-800 mb-4">Transaction Tracer</h3>
|
| 193 |
+
<div class="bg-white rounded-lg shadow-sm p-6">
|
| 194 |
+
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
| 195 |
+
<div>
|
| 196 |
+
<label for="fromAddress" class="block text-sm font-medium text-gray-700 mb-1">From Address</label>
|
| 197 |
+
<input type="text" id="fromAddress" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
|
| 198 |
+
</div>
|
| 199 |
+
<div>
|
| 200 |
+
<label for="toAddress" class="block text-sm font-medium text-gray-700 mb-1">To Address</label>
|
| 201 |
+
<input type="text" id="toAddress" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
|
| 202 |
+
</div>
|
| 203 |
+
<div>
|
| 204 |
+
<label for="txHash" class="block text-sm font-medium text-gray-700 mb-1">Transaction Hash</label>
|
| 205 |
+
<input type="text" id="txHash" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
|
| 206 |
+
</div>
|
| 207 |
+
</div>
|
| 208 |
+
<div class="mt-4 flex justify-end">
|
| 209 |
+
<button id="traceButton" class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600">
|
| 210 |
+
<i class="fas fa-search mr-1"></i> Trace Transaction
|
| 211 |
+
</button>
|
| 212 |
+
</div>
|
| 213 |
+
</div>
|
| 214 |
+
</section>
|
| 215 |
+
|
| 216 |
+
<!-- API Reference Section -->
|
| 217 |
+
<section>
|
| 218 |
+
<h3 class="text-xl font-semibold text-gray-800 mb-4">Public API Endpoints</h3>
|
| 219 |
+
<div class="bg-white rounded-lg shadow-sm overflow-hidden">
|
| 220 |
+
<div class="border-b border-gray-200">
|
| 221 |
+
<nav class="-mb-px flex">
|
| 222 |
+
<button class="api-tab active px-4 py-3 text-sm font-medium text-blue-600 border-b-2 border-blue-500">EVM Chains</button>
|
| 223 |
+
<button class="api-tab px-4 py-3 text-sm font-medium text-gray-500 hover:text-gray-700">Bitcoin</button>
|
| 224 |
+
</nav>
|
| 225 |
+
</div>
|
| 226 |
+
|
| 227 |
+
<div class="p-6">
|
| 228 |
+
<div class="api-content active">
|
| 229 |
+
<h4 class="font-medium text-gray-800 mb-2">Covalent API (Ethereum, BSC, Polygon, Arbitrum)</h4>
|
| 230 |
+
<div class="api-endpoint mb-2">https://api.covalenthq.com/v1/{chain_id}/address/{address}/transactions_v2/</div>
|
| 231 |
+
<p class="text-sm text-gray-600 mb-4">Example: <span class="api-endpoint">https://api.covalenthq.com/v1/1/address/0x1F98431c8aD98523631AE4a59f267346ea31F984/transactions_v2/</span></p>
|
| 232 |
+
|
| 233 |
+
<h4 class="font-medium text-gray-800 mb-2">Etherscan API (Ethereum)</h4>
|
| 234 |
+
<div class="api-endpoint mb-2">https://api.etherscan.io/api?module=account&action=txlist&address={address}&sort=desc</div>
|
| 235 |
+
<p class="text-sm text-gray-600">Example: <span class="api-endpoint">https://api.etherscan.io/api?module=account&action=txlist&address=0x1F98431c8aD98523631AE4a59f267346ea31F984&sort=desc</span></p>
|
| 236 |
+
</div>
|
| 237 |
+
|
| 238 |
+
<div class="api-content hidden">
|
| 239 |
+
<h4 class="font-medium text-gray-800 mb-2">Blockchair API (Bitcoin)</h4>
|
| 240 |
+
<div class="api-endpoint mb-2">https://api.blockchair.com/bitcoin/dashboards/address/{address}</div>
|
| 241 |
+
<p class="text-sm text-gray-600 mb-4">Example: <span class="api-endpoint">https://api.blockchair.com/bitcoin/dashboards/address/1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa</span></p>
|
| 242 |
+
|
| 243 |
+
<h4 class="font-medium text-gray-800 mb-2">Blockchain.com API (Bitcoin)</h4>
|
| 244 |
+
<div class="api-endpoint mb-2">https://blockchain.info/rawaddr/{address}</div>
|
| 245 |
+
<p class="text-sm text-gray-600">Example: <span class="api-endpoint">https://blockchain.info/rawaddr/1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa</span></p>
|
| 246 |
+
</div>
|
| 247 |
+
</div>
|
| 248 |
+
</div>
|
| 249 |
+
</section>
|
| 250 |
+
</main>
|
| 251 |
+
|
| 252 |
+
<!-- Footer -->
|
| 253 |
+
<footer class="bg-white border-t border-gray-200 mt-12">
|
| 254 |
+
<div class="container mx-auto px-4 py-8">
|
| 255 |
+
<div class="grid grid-cols-1 md:grid-cols-4 gap-8">
|
| 256 |
+
<div>
|
| 257 |
+
<h4 class="text-sm font-semibold text-gray-800 mb-4">EloOnChain</h4>
|
| 258 |
+
<p class="text-sm text-gray-600">
|
| 259 |
+
Open-source blockchain relationship visualizer powered by public APIs.
|
| 260 |
+
</p>
|
| 261 |
+
</div>
|
| 262 |
+
<div>
|
| 263 |
+
<h4 class="text-sm font-semibold text-gray-800 mb-4">Product</h4>
|
| 264 |
+
<ul class="space-y-2">
|
| 265 |
+
<li><a href="#" class="text-sm text-gray-600 hover:text-blue-500">Visualizer</a></li>
|
| 266 |
+
<li><a href="#" class="text-sm text-gray-600 hover:text-blue-500">Tracer</a></li>
|
| 267 |
+
<li><a href="#" class="text-sm text-gray-600 hover:text-blue-500">API Docs</a></li>
|
| 268 |
+
</ul>
|
| 269 |
+
</div>
|
| 270 |
+
<div>
|
| 271 |
+
<h4 class="text-sm font-semibold text-gray-800 mb-4">Resources</h4>
|
| 272 |
+
<ul class="space-y-2">
|
| 273 |
+
<li><a href="#" class="text-sm text-gray-600 hover:text-blue-500">Documentation</a></li>
|
| 274 |
+
<li><a href="#" class="text-sm text-gray-600 hover:text-blue-500">GitHub</a></li>
|
| 275 |
+
<li><a href="#" class="text-sm text-gray-600 hover:text-blue-500">Blog</a></li>
|
| 276 |
+
</ul>
|
| 277 |
+
</div>
|
| 278 |
+
<div>
|
| 279 |
+
<h4 class="text-sm font-semibold text-gray-800 mb-4">Connect</h4>
|
| 280 |
+
<div class="flex space-x-4">
|
| 281 |
+
<a href="#" class="text-gray-500 hover:text-blue-500"><i class="fab fa-twitter"></i></a>
|
| 282 |
+
<a href="#" class="text-gray-500 hover:text-blue-500"><i class="fab fa-github"></i></a>
|
| 283 |
+
<a href="#" class="text-gray-500 hover:text-blue-500"><i class="fab fa-discord"></i></a>
|
| 284 |
+
<a href="#" class="text-gray-500 hover:text-blue-500"><i class="fab fa-telegram"></i></a>
|
| 285 |
+
</div>
|
| 286 |
+
</div>
|
| 287 |
+
</div>
|
| 288 |
+
<div class="border-t border-gray-200 mt-8 pt-8 text-sm text-gray-500">
|
| 289 |
+
<p>© 2023 EloOnChain. All rights reserved.</p>
|
| 290 |
+
</div>
|
| 291 |
+
</div>
|
| 292 |
+
</footer>
|
| 293 |
+
|
| 294 |
+
<!-- Add Address Modal -->
|
| 295 |
+
<div id="addAddressModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
|
| 296 |
+
<div class="bg-white rounded-lg shadow-xl w-full max-w-md">
|
| 297 |
+
<div class="p-6">
|
| 298 |
+
<div class="flex justify-between items-center mb-4">
|
| 299 |
+
<h3 class="text-lg font-medium text-gray-800">Add Wallet Address</h3>
|
| 300 |
+
<button id="closeModal" class="text-gray-500 hover:text-gray-700">
|
| 301 |
+
<i class="fas fa-times"></i>
|
| 302 |
+
</button>
|
| 303 |
+
</div>
|
| 304 |
+
<div class="mb-4">
|
| 305 |
+
<label for="newAddress" class="block text-sm font-medium text-gray-700 mb-1">Wallet Address</label>
|
| 306 |
+
<input type="text" id="newAddress" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
|
| 307 |
+
</div>
|
| 308 |
+
<div class="mb-4">
|
| 309 |
+
<label for="addressLabel" class="block text-sm font-medium text-gray-700 mb-1">Label (Optional)</label>
|
| 310 |
+
<input type="text" id="addressLabel" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-blue-500 focus:border-blue-500">
|
| 311 |
+
</div>
|
| 312 |
+
<div class="mb-4">
|
| 313 |
+
<label class="block text-sm font-medium text-gray-700 mb-1">Type</label>
|
| 314 |
+
<div class="flex space-x-4">
|
| 315 |
+
<label class="inline-flex items-center">
|
| 316 |
+
<input type="radio" name="addressType" value="wallet" class="h-4 w-4 text-blue-600" checked>
|
| 317 |
+
<span class="ml-2 text-sm text-gray-700">Wallet</span>
|
| 318 |
+
</label>
|
| 319 |
+
<label class="inline-flex items-center">
|
| 320 |
+
<input type="radio" name="addressType" value="contract" class="h-4 w-4 text-blue-600">
|
| 321 |
+
<span class="ml-2 text-sm text-gray-700">Contract</span>
|
| 322 |
+
</label>
|
| 323 |
+
<label class="inline-flex items-center">
|
| 324 |
+
<input type="radio" name="addressType" value="exchange" class="h-4 w-4 text-blue-600">
|
| 325 |
+
<span class="ml-2 text-sm text-gray-700">Exchange</span>
|
| 326 |
+
</label>
|
| 327 |
+
</div>
|
| 328 |
+
</div>
|
| 329 |
+
<div class="flex justify-end space-x-3">
|
| 330 |
+
<button id="cancelAddAddress" class="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-md hover:bg-gray-200">
|
| 331 |
+
Cancel
|
| 332 |
+
</button>
|
| 333 |
+
<button id="confirmAddAddress" class="px-4 py-2 text-sm font-medium text-white bg-blue-500 rounded-md hover:bg-blue-600">
|
| 334 |
+
Add Address
|
| 335 |
+
</button>
|
| 336 |
+
</div>
|
| 337 |
+
</div>
|
| 338 |
+
</div>
|
| 339 |
+
</div>
|
| 340 |
+
|
| 341 |
+
<script>
|
| 342 |
+
// Initialize the network visualization
|
| 343 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 344 |
+
// Sample data for the visualization
|
| 345 |
+
const nodes = new vis.DataSet([
|
| 346 |
+
{id: 1, label: '0x1F984...', title: 'Uniswap V3', group: 'contract'},
|
| 347 |
+
{id: 2, label: '0xA0b869...', title: 'USDC Contract', group: 'contract'},
|
| 348 |
+
{id: 3, label: '0x123456...', title: 'User Wallet', group: 'wallet'},
|
| 349 |
+
{id: 4, label: '0x789abc...', title: 'Binance', group: 'exchange'},
|
| 350 |
+
{id: 5, label: '0xdef123...', title: 'User Wallet 2', group: 'wallet'}
|
| 351 |
+
]);
|
| 352 |
+
|
| 353 |
+
const edges = new vis.DataSet([
|
| 354 |
+
{from: 3, to: 1, label: '2.5 ETH', title: 'Tx: 0x123...456'},
|
| 355 |
+
{from: 1, to: 3, label: '500 USDC', title: 'Tx: 0x789...abc'},
|
| 356 |
+
{from: 3, to: 4, label: '1.2 ETH', title: 'Tx: 0xdef...123'},
|
| 357 |
+
{from: 4, to: 5, label: '0.8 ETH', title: 'Tx: 0x456...789'},
|
| 358 |
+
{from: 5, to: 2, label: '1000 USDC', title: 'Tx: 0xabc...def'},
|
| 359 |
+
{from: 2, to: 1, label: '800 USDC', title: 'Tx: 0x321...654'}
|
| 360 |
+
]);
|
| 361 |
+
|
| 362 |
+
const container = document.getElementById('network');
|
| 363 |
+
const data = {
|
| 364 |
+
nodes: nodes,
|
| 365 |
+
edges: edges
|
| 366 |
+
};
|
| 367 |
+
|
| 368 |
+
const options = {
|
| 369 |
+
nodes: {
|
| 370 |
+
shape: 'box',
|
| 371 |
+
shadow: true,
|
| 372 |
+
font: {
|
| 373 |
+
size: 14,
|
| 374 |
+
color: '#ffffff'
|
| 375 |
+
},
|
| 376 |
+
borderWidth: 0,
|
| 377 |
+
widthConstraint: {
|
| 378 |
+
minimum: 100,
|
| 379 |
+
maximum: 150
|
| 380 |
+
}
|
| 381 |
+
},
|
| 382 |
+
edges: {
|
| 383 |
+
arrows: 'to',
|
| 384 |
+
smooth: {
|
| 385 |
+
type: 'cubicBezier',
|
| 386 |
+
roundness: 0.2
|
| 387 |
+
},
|
| 388 |
+
font: {
|
| 389 |
+
size: 12,
|
| 390 |
+
align: 'middle'
|
| 391 |
+
},
|
| 392 |
+
color: {
|
| 393 |
+
color: '#d1d5db',
|
| 394 |
+
highlight: '#93c5fd'
|
| 395 |
+
}
|
| 396 |
+
},
|
| 397 |
+
groups: {
|
| 398 |
+
wallet: {
|
| 399 |
+
color: {
|
| 400 |
+
background: '#10b981',
|
| 401 |
+
border: '#059669',
|
| 402 |
+
highlight: {
|
| 403 |
+
background: '#34d399',
|
| 404 |
+
border: '#059669'
|
| 405 |
+
}
|
| 406 |
+
}
|
| 407 |
+
},
|
| 408 |
+
contract: {
|
| 409 |
+
color: {
|
| 410 |
+
background: '#3b82f6',
|
| 411 |
+
border: '#2563eb',
|
| 412 |
+
highlight: {
|
| 413 |
+
background: '#60a5fa',
|
| 414 |
+
border: '#2563eb'
|
| 415 |
+
}
|
| 416 |
+
}
|
| 417 |
+
},
|
| 418 |
+
exchange: {
|
| 419 |
+
color: {
|
| 420 |
+
background: '#f59e0b',
|
| 421 |
+
border: '#d97706',
|
| 422 |
+
highlight: {
|
| 423 |
+
background: '#fbbf24',
|
| 424 |
+
border: '#d97706'
|
| 425 |
+
}
|
| 426 |
+
}
|
| 427 |
+
}
|
| 428 |
+
},
|
| 429 |
+
physics: {
|
| 430 |
+
solver: 'forceAtlas2Based',
|
| 431 |
+
forceAtlas2Based: {
|
| 432 |
+
gravitationalConstant: -50,
|
| 433 |
+
centralGravity: 0.01,
|
| 434 |
+
springLength: 200,
|
| 435 |
+
springConstant: 0.08,
|
| 436 |
+
damping: 0.4
|
| 437 |
+
},
|
| 438 |
+
maxVelocity: 50,
|
| 439 |
+
minVelocity: 0.1
|
| 440 |
+
},
|
| 441 |
+
interaction: {
|
| 442 |
+
hover: true,
|
| 443 |
+
tooltipDelay: 200
|
| 444 |
+
}
|
| 445 |
+
};
|
| 446 |
+
|
| 447 |
+
const network = new vis.Network(container, data, options);
|
| 448 |
+
|
| 449 |
+
// Search functionality
|
| 450 |
+
const addressSearch = document.getElementById('addressSearch');
|
| 451 |
+
const searchButton = document.getElementById('searchButton');
|
| 452 |
+
const searchDropdown = document.getElementById('searchDropdown');
|
| 453 |
+
|
| 454 |
+
// Sample addresses for autocomplete
|
| 455 |
+
const sampleAddresses = [
|
| 456 |
+
{address: '0x1F98431c8aD98523631AE4a59f267346ea31F984', label: 'Uniswap V3', type: 'contract'},
|
| 457 |
+
{address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', label: 'USDC Contract', type: 'contract'},
|
| 458 |
+
{address: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D', label: 'Uniswap Router', type: 'contract'},
|
| 459 |
+
{address: '0x5a52e96bacdabb82fd05763e25335261b270efcb', label: 'Binance 8', type: 'exchange'},
|
| 460 |
+
{address: '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', label: 'Satoshi Wallet', type: 'wallet'},
|
| 461 |
+
{address: '3FZbgi29cpjq2GjdwV8eyHuJJnkLtktZc5', label: 'Bitfinex', type: 'exchange'}
|
| 462 |
+
];
|
| 463 |
+
|
| 464 |
+
addressSearch.addEventListener('input', function() {
|
| 465 |
+
const searchTerm = this.value.toLowerCase();
|
| 466 |
+
if (searchTerm.length > 2) {
|
| 467 |
+
const matches = sampleAddresses.filter(addr =>
|
| 468 |
+
addr.address.toLowerCase().includes(searchTerm) ||
|
| 469 |
+
addr.label.toLowerCase().includes(searchTerm)
|
| 470 |
+
);
|
| 471 |
+
|
| 472 |
+
if (matches.length > 0) {
|
| 473 |
+
searchDropdown.innerHTML = '';
|
| 474 |
+
matches.forEach(match => {
|
| 475 |
+
const item = document.createElement('div');
|
| 476 |
+
item.className = 'search-dropdown-item';
|
| 477 |
+
item.innerHTML = `
|
| 478 |
+
<div class="font-medium">${match.label}</div>
|
| 479 |
+
<div class="text-xs text-gray-500">${match.address}</div>
|
| 480 |
+
`;
|
| 481 |
+
item.addEventListener('click', function() {
|
| 482 |
+
addressSearch.value = match.address;
|
| 483 |
+
searchDropdown.classList.remove('show');
|
| 484 |
+
});
|
| 485 |
+
searchDropdown.appendChild(item);
|
| 486 |
+
});
|
| 487 |
+
searchDropdown.classList.add('show');
|
| 488 |
+
} else {
|
| 489 |
+
searchDropdown.classList.remove('show');
|
| 490 |
+
}
|
| 491 |
+
} else {
|
| 492 |
+
searchDropdown.classList.remove('show');
|
| 493 |
+
}
|
| 494 |
+
});
|
| 495 |
+
|
| 496 |
+
document.addEventListener('click', function(e) {
|
| 497 |
+
if (!addressSearch.contains(e.target) && !searchDropdown.contains(e.target)) {
|
| 498 |
+
searchDropdown.classList.remove('show');
|
| 499 |
+
}
|
| 500 |
+
});
|
| 501 |
+
|
| 502 |
+
searchButton.addEventListener('click', function() {
|
| 503 |
+
const address = addressSearch.value.trim();
|
| 504 |
+
if (address) {
|
| 505 |
+
// In a real app, this would fetch data from the API
|
| 506 |
+
alert(`Searching for address: ${address}`);
|
| 507 |
+
}
|
| 508 |
+
});
|
| 509 |
+
|
| 510 |
+
// Add address modal functionality
|
| 511 |
+
const addAddressBtn = document.getElementById('addAddressBtn');
|
| 512 |
+
const addAddressModal = document.getElementById('addAddressModal');
|
| 513 |
+
const closeModal = document.getElementById('closeModal');
|
| 514 |
+
const cancelAddAddress = document.getElementById('cancelAddAddress');
|
| 515 |
+
const confirmAddAddress = document.getElementById('confirmAddAddress');
|
| 516 |
+
|
| 517 |
+
addAddressBtn.addEventListener('click', function() {
|
| 518 |
+
addAddressModal.classList.remove('hidden');
|
| 519 |
+
});
|
| 520 |
+
|
| 521 |
+
closeModal.addEventListener('click', function() {
|
| 522 |
+
addAddressModal.classList.add('hidden');
|
| 523 |
+
});
|
| 524 |
+
|
| 525 |
+
cancelAddAddress.addEventListener('click', function() {
|
| 526 |
+
addAddressModal.classList.add('hidden');
|
| 527 |
+
});
|
| 528 |
+
|
| 529 |
+
confirmAddAddress.addEventListener('click', function() {
|
| 530 |
+
const newAddress = document.getElementById('newAddress').value.trim();
|
| 531 |
+
const addressLabel = document.getElementById('addressLabel').value.trim();
|
| 532 |
+
const addressType = document.querySelector('input[name="addressType"]:checked').value;
|
| 533 |
+
|
| 534 |
+
if (newAddress) {
|
| 535 |
+
// In a real app, this would validate the address and add it to the graph
|
| 536 |
+
const label = addressLabel || newAddress.substring(0, 6) + '...' + newAddress.substring(newAddress.length - 4);
|
| 537 |
+
|
| 538 |
+
nodes.add({
|
| 539 |
+
id: nodes.length + 1,
|
| 540 |
+
label: label,
|
| 541 |
+
title: newAddress,
|
| 542 |
+
group: addressType
|
| 543 |
+
});
|
| 544 |
+
|
| 545 |
+
// Reset form and close modal
|
| 546 |
+
document.getElementById('newAddress').value = '';
|
| 547 |
+
document.getElementById('addressLabel').value = '';
|
| 548 |
+
addAddressModal.classList.add('hidden');
|
| 549 |
+
}
|
| 550 |
+
});
|
| 551 |
+
|
| 552 |
+
// API tabs functionality
|
| 553 |
+
const apiTabs = document.querySelectorAll('.api-tab');
|
| 554 |
+
const apiContents = document.querySelectorAll('.api-content');
|
| 555 |
+
|
| 556 |
+
apiTabs.forEach((tab, index) => {
|
| 557 |
+
tab.addEventListener('click', function() {
|
| 558 |
+
// Remove active class from all tabs and contents
|
| 559 |
+
apiTabs.forEach(t => t.classList.remove('active'));
|
| 560 |
+
apiContents.forEach(c => c.classList.add('hidden'));
|
| 561 |
+
|
| 562 |
+
// Add active class to clicked tab and corresponding content
|
| 563 |
+
this.classList.add('active');
|
| 564 |
+
apiContents[index].classList.remove('hidden');
|
| 565 |
+
});
|
| 566 |
+
});
|
| 567 |
+
|
| 568 |
+
// Export graph functionality
|
| 569 |
+
const exportGraph = document.getElementById('exportGraph');
|
| 570 |
+
exportGraph.addEventListener('click', function() {
|
| 571 |
+
// In a real app, this would export the graph as an image or JSON
|
| 572 |
+
alert('Export functionality would be implemented here');
|
| 573 |
+
});
|
| 574 |
+
|
| 575 |
+
// Trace transaction functionality
|
| 576 |
+
const traceButton = document.getElementById('traceButton');
|
| 577 |
+
traceButton.addEventListener('click', function() {
|
| 578 |
+
const fromAddress = document.getElementById('fromAddress').value.trim();
|
| 579 |
+
const toAddress = document.getElementById('toAddress').value.trim();
|
| 580 |
+
const txHash = document.getElementById('txHash').value.trim();
|
| 581 |
+
|
| 582 |
+
if (fromAddress || toAddress || txHash) {
|
| 583 |
+
// In a real app, this would trace the transaction
|
| 584 |
+
alert(`Tracing transaction with:\nFrom: ${fromAddress}\nTo: ${toAddress}\nHash: ${txHash}`);
|
| 585 |
+
} else {
|
| 586 |
+
alert('Please enter at least one field to trace');
|
| 587 |
+
}
|
| 588 |
+
});
|
| 589 |
+
});
|
| 590 |
+
</script>
|
| 591 |
+
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=akagelks/eloonchain" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
|
| 592 |
+
</html>
|