Spaces:
Running
Running
| <html lang="ar" dir="rtl"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>مشروع عملة رقمية - المحاكاة الكاملة | ArabChain</title> | |
| <!-- Fonts & Icons --> | |
| <link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <style> | |
| :root { | |
| --primary: #00f2ea; | |
| --secondary: #ff0050; | |
| --bg-dark: #0b0c15; | |
| --bg-panel: #151621; | |
| --text-main: #ffffff; | |
| --text-muted: #8f90a6; | |
| --glass: rgba(255, 255, 255, 0.05); | |
| --border: rgba(255, 255, 255, 0.1); | |
| --success: #00d26a; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| font-family: 'Tajawal', sans-serif; | |
| scrollbar-width: thin; | |
| scrollbar-color: var(--primary) var(--bg-dark); | |
| } | |
| body { | |
| background-color: var(--bg-dark); | |
| color: var(--text-main); | |
| display: flex; | |
| flex-direction: column; | |
| height: 100vh; | |
| overflow: hidden; | |
| } | |
| /* Header */ | |
| header { | |
| height: 60px; | |
| background: var(--bg-panel); | |
| border-bottom: 1px solid var(--border); | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| padding: 0 20px; | |
| z-index: 100; | |
| } | |
| .brand { | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| background: linear-gradient(45deg, var(--primary), var(--secondary)); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .anycoder-link { | |
| color: var(--text-muted); | |
| text-decoration: none; | |
| font-size: 0.9rem; | |
| transition: color 0.3s; | |
| border: 1px solid var(--border); | |
| padding: 5px 15px; | |
| border-radius: 20px; | |
| } | |
| .anycoder-link:hover { | |
| color: var(--primary); | |
| border-color: var(--primary); | |
| } | |
| /* Layout */ | |
| .main-container { | |
| display: flex; | |
| flex: 1; | |
| overflow: hidden; | |
| } | |
| /* Sidebar */ | |
| aside { | |
| width: 250px; | |
| background: var(--bg-panel); | |
| border-left: 1px solid var(--border); | |
| display: flex; | |
| flex-direction: column; | |
| padding: 20px 0; | |
| transition: transform 0.3s ease; | |
| } | |
| .nav-item { | |
| padding: 15px 25px; | |
| cursor: pointer; | |
| color: var(--text-muted); | |
| display: flex; | |
| align-items: center; | |
| gap: 15px; | |
| transition: all 0.3s; | |
| border-right: 3px solid transparent; | |
| } | |
| .nav-item:hover, .nav-item.active { | |
| background: var(--glass); | |
| color: var(--primary); | |
| border-right-color: var(--primary); | |
| } | |
| /* Content Area */ | |
| main { | |
| flex: 1; | |
| padding: 30px; | |
| overflow-y: auto; | |
| position: relative; | |
| } | |
| .section { | |
| display: none; | |
| animation: fadeIn 0.5s ease; | |
| } | |
| .section.active { | |
| display: block; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| /* Dashboard Cards */ | |
| .stats-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); | |
| gap: 20px; | |
| margin-bottom: 30px; | |
| } | |
| .card { | |
| background: var(--bg-panel); | |
| border: 1px solid var(--border); | |
| border-radius: 12px; | |
| padding: 20px; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 2px; | |
| background: linear-gradient(90deg, var(--primary), transparent); | |
| } | |
| .card h3 { | |
| font-size: 0.9rem; | |
| color: var(--text-muted); | |
| margin-bottom: 10px; | |
| } | |
| .card .value { | |
| font-size: 1.8rem; | |
| font-weight: 700; | |
| } | |
| .pulse { | |
| animation: pulse-animation 2s infinite; | |
| } | |
| @keyframes pulse-animation { | |
| 0% { box-shadow: 0 0 0 0 rgba(0, 242, 234, 0.4); } | |
| 70% { box-shadow: 0 0 0 10px rgba(0, 242, 234, 0); } | |
| 100% { box-shadow: 0 0 0 0 rgba(0, 242, 234, 0); } | |
| } | |
| /* Blockchain Visualization */ | |
| .blocks-container { | |
| display: flex; | |
| gap: 20px; | |
| overflow-x: auto; | |
| padding-bottom: 20px; | |
| align-items: center; | |
| } | |
| .block { | |
| min-width: 220px; | |
| background: var(--bg-panel); | |
| border: 1px solid var(--border); | |
| border-radius: 8px; | |
| padding: 15px; | |
| font-family: monospace; | |
| font-size: 0.85rem; | |
| position: relative; | |
| } | |
| .block-header { | |
| display: flex; | |
| justify-content: space-between; | |
| margin-bottom: 10px; | |
| color: var(--primary); | |
| font-weight: bold; | |
| } | |
| .hash { | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| color: var(--text-muted); | |
| margin-bottom: 5px; | |
| } | |
| .chain-link { | |
| min-width: 30px; | |
| height: 2px; | |
| background: var(--text-muted); | |
| } | |
| /* Code Editor Simulation */ | |
| .editor-container { | |
| background: #000; | |
| border-radius: 8px; | |
| border: 1px solid var(--border); | |
| font-family: 'Fira Code', monospace; | |
| overflow: hidden; | |
| } | |
| .editor-header { | |
| background: #1e1e1e; | |
| padding: 10px; | |
| display: flex; | |
| gap: 10px; | |
| } | |
| .dot { width: 12px; height: 12px; border-radius: 50%; } | |
| .red { background: #ff5f56; } | |
| .yellow { background: #ffbd2e; } | |
| .green { background: #27c93f; } | |
| textarea.code-area { | |
| width: 100%; | |
| height: 300px; | |
| background: #0d0d0d; | |
| color: #d4d4d4; | |
| border: none; | |
| padding: 15px; | |
| resize: none; | |
| outline: none; | |
| font-family: monospace; | |
| } | |
| .btn { | |
| background: var(--primary); | |
| color: #000; | |
| border: none; | |
| padding: 10px 20px; | |
| border-radius: 6px; | |
| cursor: pointer; | |
| font-weight: 600; | |
| transition: 0.3s; | |
| } | |
| .btn:hover { | |
| opacity: 0.9; | |
| transform: translateY(-2px); | |
| } | |
| .btn-outline { | |
| background: transparent; | |
| border: 1px solid var(--primary); | |
| color: var(--primary); | |
| } | |
| /* P2P Network Canvas */ | |
| #networkCanvas { | |
| width: 100%; | |
| height: 300px; | |
| background: #000; | |
| border-radius: 12px; | |
| border: 1px solid var(--border); | |
| } | |
| /* Logs */ | |
| .console-log { | |
| background: #000; | |
| color: #0f0; | |
| font-family: monospace; | |
| height: 200px; | |
| overflow-y: auto; | |
| padding: 10px; | |
| border-radius: 8px; | |
| border: 1px solid var(--border); | |
| margin-top: 20px; | |
| font-size: 0.8rem; | |
| } | |
| /* Wallet UI */ | |
| .wallet-layout { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 20px; | |
| } | |
| .form-group { | |
| margin-bottom: 15px; | |
| } | |
| .form-group label { | |
| display: block; | |
| margin-bottom: 5px; | |
| color: var(--text-muted); | |
| } | |
| .form-group input { | |
| width: 100%; | |
| padding: 10px; | |
| background: var(--bg-dark); | |
| border: 1px solid var(--border); | |
| color: #fff; | |
| border-radius: 6px; | |
| } | |
| /* Responsive */ | |
| @media (max-width: 768px) { | |
| .main-container { | |
| flex-direction: column; | |
| } | |
| aside { | |
| width: 100%; | |
| flex-direction: row; | |
| overflow-x: auto; | |
| padding: 10px; | |
| border-left: none; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .nav-item { | |
| padding: 10px; | |
| white-space: nowrap; | |
| border-right: none; | |
| border-bottom: 3px solid transparent; | |
| } | |
| .nav-item:hover, .nav-item.active { | |
| border-bottom-color: var(--primary); | |
| } | |
| .wallet-layout { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <div class="brand"> | |
| <i class="fa-solid fa-cube"></i> ArabChain Core | |
| </div> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link"> | |
| Built with anycoder | |
| </a> | |
| </header> | |
| <div class="main-container"> | |
| <aside> | |
| <div class="nav-item active" onclick="showSection('dashboard')"> | |
| <i class="fa-solid fa-chart-line"></i> لوحة التحكم | |
| </div> | |
| <div class="nav-item" onclick="showSection('blockchain')"> | |
| <i class="fa-solid fa-link"></i> المستكشف (Explorer) | |
| </div> | |
| <div class="nav-item" onclick="showSection('wallet')"> | |
| <i class="fa-solid fa-wallet"></i> المحفظة (Wallet) | |
| </div> | |
| <div class="nav-item" onclick="showSection('consensus')"> | |
| <i class="fa-solid fa-users-gear"></i> الإجماع (PoS) | |
| </div> | |
| <div class="nav-item" onclick="showSection('smart-contracts')"> | |
| <i class="fa-solid fa-code"></i> العقود الذكية | |
| </div> | |
| <div class="nav-item" onclick="showSection('network')"> | |
| <i class="fa-solid fa-network-wired"></i> شبكة P2P | |
| </div> | |
| <div class="nav-item" onclick="showSection('docs')"> | |
| <i class="fa-solid fa-book"></i> التوثيق & Docker | |
| </div> | |
| </aside> | |
| <main> | |
| <!-- DASHBOARD --> | |
| <div id="dashboard" class="section active"> | |
| <h2>نظرة عامة على الشبكة (Mainnet)</h2> | |
| <br> | |
| <div class="stats-grid"> | |
| <div class="card"> | |
| <h3>رقم الكتلة (Height)</h3> | |
| <div class="value" id="blockHeight">0</div> | |
| </div> | |
| <div class="card"> | |
| <h3>المعاملات (TPS)</h3> | |
| <div class="value" id="tps">0</div> | |
| </div> | |
| <div class="card"> | |
| <h3>العقد النشطة (Peers)</h3> | |
| <div class="value">1,240</div> | |
| </div> | |
| <div class="card"> | |
| <h3>سعر العملة (ARC)</h3> | |
| <div class="value">$142.50</div> | |
| </div> | |
| </div> | |
| <h3>سجل النظام (System Logs)</h3> | |
| <div class="console-log" id="systemLog"> | |
| <div>[SYSTEM] Initializing ArabChain Protocol v1.0...</div> | |
| <div>[NET] P2P Listener started on port 30303</div> | |
| <div>[CONSENSUS] Proof of Stake engine initialized.</div> | |
| </div> | |
| </div> | |
| <!-- BLOCKCHAIN EXPLORER --> | |
| <div id="blockchain" class="section"> | |
| <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:20px;"> | |
| <h2>سلسلة الكتل (Blockchain Live)</h2> | |
| <button class="btn btn-outline" onclick="manualMine()">تعدين كتلة يدوياً</button> | |
| </div> | |
| <div class="blocks-container" id="chainContainer"> | |
| <!-- Blocks will be injected here via JS --> | |
| </div> | |
| </div> | |
| <!-- WALLET --> | |
| <div id="wallet" class="section"> | |
| <h2>المحفظة الرقمية (Web Wallet)</h2> | |
| <br> | |
| <div class="wallet-layout"> | |
| <div class="card"> | |
| <h3>رصيدك الحالي</h3> | |
| <div class="value" style="color:var(--primary);">2,500.00 ARC</div> | |
| <p style="color:var(--text-muted); font-size:0.8rem; margin-top:10px;">العنوان: <span id="myAddress">0x7a...3f9</span></p> | |
| <br> | |
| <div style="display:flex; gap:10px;"> | |
| <button class="btn"><i class="fa-solid fa-paper-plane"></i> إرسال</button> | |
| <button class="btn btn-outline"><i class="fa-solid fa-qrcode"></i> استلام</button> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <h3>إرسال عملات</h3> | |
| <div class="form-group"> | |
| <label>عنوان المستلم</label> | |
| <input type="text" placeholder="0x..."> | |
| </div> | |
| <div class="form-group"> | |
| <label>المبلغ (ARC)</label> | |
| <input type="number" placeholder="0.00"> | |
| </div> | |
| <button class="btn" style="width:100%" onclick="simulateTx()">تأكيد المعاملة</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- CONSENSUS --> | |
| <div id="consensus" class="section"> | |
| <h2>نظام الإجماع (Proof of Stake)</h2> | |
| <p style="color:var(--text-muted); margin-bottom:20px;">المصادقون (Validators) النشطون حالياً في الشبكة.</p> | |
| <div class="stats-grid"> | |
| <div class="card"> | |
| <h3>إجمالي المخزن (Staked)</h3> | |
| <div class="value">14M ARC</div> | |
| </div> | |
| <div class="card"> | |
| <h3>المصادقون</h3> | |
| <div class="value">84</div> | |
| </div> | |
| </div> | |
| <table style="width:100%; text-align:right; border-collapse:collapse; margin-top:20px;"> | |
| <thead> | |
| <tr style="border-bottom:1px solid var(--border); color:var(--text-muted);"> | |
| <th style="padding:10px;">المصادق (Validator)</th> | |
| <th>الكمية المخزنة</th> | |
| <th>الحالة</th> | |
| <th>الكتل المنتجة</th> | |
| </tr> | |
| </thead> | |
| <tbody id="validatorsTable"> | |
| <!-- JS Populated --> | |
| </tbody> | |
| </table> | |
| </div> | |
| <!-- SMART CONTRACTS --> | |
| <div id="smart-contracts" class="section"> | |
| <h2>محرك العقود الذكية (ArabEVM)</h2> | |
| <p style="color:var(--text-muted); margin-bottom:15px;">اكتب وانشر العقود الذكية باستخدام لغة Solidity.</p> | |
| <div class="editor-container"> | |
| <div class="editor-header"> | |
| <div class="dot red"></div> | |
| <div class="dot yellow"></div> | |
| <div class="dot green"></div> | |
| <span style="margin-right:auto; color:#888; font-size:0.8rem;">Token.sol</span> | |
| </div> | |
| <textarea class="code-area" spellcheck="false"> | |
| pragma solidity ^0.8.0; | |
| contract ArabToken { | |
| string public name = "ArabCoin"; | |
| string public symbol = "ARC"; | |
| uint256 public totalSupply = 1000000; | |
| mapping(address => uint256) balances; | |
| constructor() { | |
| balances[msg.sender] = totalSupply; | |
| } | |
| function transfer(address to, uint256 amount) external { | |
| require(balances[msg.sender] >= amount, "No funds"); | |
| balances[msg.sender] -= amount; | |
| balances[to] += amount; | |
| } | |
| } | |
| </textarea> | |
| </div> | |
| <div style="margin-top:15px;"> | |
| <button class="btn" onclick="deployContract()"><i class="fa-solid fa-rocket"></i> نشر العقد (Deploy)</button> | |
| <span id="deployStatus" style="margin-right:10px; color:var(--success); display:none;">تم النشر بنجاح! Hash: 0x8f...2a</span> | |
| </div> | |
| </div> | |
| <!-- P2P NETWORK --> | |
| <div id="network" class="section"> | |
| <h2>شبكة النظير للنظير (P2P Network Visualization)</h2> | |
| <p style="color:var(--text-muted);">تصور حي لانتشار الكتل والمعاملات بين العقد.</p> | |
| <br> | |
| <canvas id="networkCanvas"></canvas> | |
| </div> | |
| <!-- DOCS & DOCKER --> | |
| <div id="docs" class="section"> | |
| <h2>التوثيق والتشغيل (Documentation)</h2> | |
| <div class="card" style="margin-top:20px;"> | |
| <h3><i class="fa-brands fa-docker"></i> التشغيل باستخدام Docker</h3> | |
| <p style="color:var(--text-muted); margin-bottom:10px;">لتشغيل عقدة كاملة (Full Node) محلياً:</p> | |
| <div class="editor-container"> | |
| <textarea class="code-area" style="height:150px; font-size:0.9rem;" readonly> | |
| # docker-compose.yml | |
| version: '3' | |
| services: | |
| arabchain-node: | |
| image: arabchain/core:latest | |
| ports: | |
| - "30303:30303" # P2P | |
| - "8545:8545" # JSON-RPC | |
| volumes: | |
| - ./data:/root/.arabchain | |
| command: --network mainnet --sync-mode full | |
| </textarea> | |
| </div> | |
| </div> | |
| <div class="card" style="margin-top:20px;"> | |
| <h3><i class="fa-solid fa-server"></i> JSON-RPC API</h3> | |
| <p style="color:var(--text-muted);">مثال على طلب رصيد باستخدام cURL:</p> | |
| <div class="editor-container"> | |
| <textarea class="code-area" style="height:80px; font-size:0.9rem;" readonly> | |
| curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"],"id":1}' -H "Content-Type: application/json" localhost:8545 | |
| </textarea> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <script> | |
| // --- Navigation Logic --- | |
| function showSection(id) { | |
| document.querySelectorAll('.section').forEach(sec => sec.classList.remove('active')); | |
| document.getElementById(id).classList.add('active'); | |
| document.querySelectorAll('.nav-item').forEach(item => item.classList.remove('active')); | |
| event.currentTarget.classList.add('active'); | |
| if(id === 'network') initNetworkVis(); | |
| } | |
| // --- Blockchain Logic (Simulation) --- | |
| let blocks = []; | |
| let blockHeight = 0; | |
| const maxBlocksDisplay = 5; | |
| function generateHash() { | |
| return '0x' + Array(64).fill(0).map(() => Math.floor(Math.random() * 16).toString(16)).join(''); | |
| } | |
| function createBlock(isManual = false) { | |
| blockHeight++; | |
| const prevHash = blocks.length > 0 ? blocks[blocks.length - 1].hash.substring(0, 10) + "..." : "0x000000..."; | |
| const newBlock = { | |
| height: blockHeight, | |
| hash: generateHash(), | |
| prevHash: prevHash, | |
| txs: Math.floor(Math.random() * 50) + 1, | |
| validator: "Validator_" + Math.floor(Math.random() * 10), | |
| time: new Date().toLocaleTimeString() | |
| }; | |
| blocks.push(newBlock); | |
| document.getElementById('blockHeight').innerText = blockHeight; | |
| // Update TPS (random fluctuation) | |
| document.getElementById('tps').innerText = Math.floor(Math.random() * 2000) + 500; | |
| renderBlock(newBlock); | |
| log(`[BLOCKCHAIN] New block #${blockHeight} forged by ${newBlock.validator}`); | |
| if (isManual) { | |
| alert("تم تعدين الكتلة بنجاح!"); | |
| } | |
| } | |
| function renderBlock(block) { | |
| const container = document.getElementById('chainContainer'); | |
| const blockDiv = document.createElement('div'); | |
| blockDiv.className = 'block'; | |
| blockDiv.innerHTML = ` | |
| <div class="block-header"> | |
| <span>#${block.height}</span> | |
| <span>${block.time}</span> | |
| </div> | |
| <div style="font-size:0.7rem; color:#888;">HASH</div> | |
| <div class="hash">${block.hash}</div> | |
| <div style="font-size:0.7rem; color:#888;">PREV HASH</div> | |
| <div class="hash">${block.prevHash}</div> | |
| <div style="margin-top:10px; display:flex; justify-content:space-between; font-size:0.8rem;"> | |
| <span><i class="fa-solid fa-list"></i> ${block.txs} Txs</span> | |
| <span style="color:var(--primary);">${block.validator}</span> | |
| </div> | |
| `; | |
| // Add link if not first | |
| if (blocks.length > 1) { | |
| const link = document.createElement('div'); | |
| link.className = 'chain-link'; | |
| container.prepend(link); | |
| } | |
| container.prepend(blockDiv); | |
| // Keep DOM clean | |
| if (container.children.length > maxBlocksDisplay * 2) { | |
| container.lastElementChild.remove(); | |
| container.lastElementChild.remove(); | |
| } | |
| } | |
| function log(msg) { | |
| const logDiv = document.getElementById('systemLog'); | |
| const entry = document.createElement('div'); | |
| entry.innerText = `> ${msg}`; | |
| logDiv.prepend(entry); | |
| } | |
| function manualMine() { | |
| createBlock(true); | |
| } | |
| function simulateTx() { | |
| log("[MEMPOOL] Transaction submitted: 0x" + Math.floor(Math.random()*100000)); | |
| setTimeout(() => alert("تم إرسال المعاملة إلى الشبكة!"), 500); | |
| } | |
| function deployContract() { | |
| log("[EVM] Compiling Solidity code..."); | |
| setTimeout(() => { | |
| log("[EVM] Contract deployed at 0x71C...9A"); | |
| document.getElementById('deployStatus').style.display = 'inline-block'; | |
| }, 1500); | |
| } | |
| // --- Validators Mock Data --- | |
| const validators = [ | |
| { name: "Binance Node", stake: "2.5M", status: "Active", blocks: 1240 }, | |
| { name: "ArabChain Foundation", stake: "5M", status: "Active", blocks: 3100 }, | |
| { name: "Community Node 1", stake: "500K", status: "Active", blocks: 420 }, | |
| { name: "Kraken Validator", stake: "1.2M", status: "Active", blocks: 890 }, | |
| ]; | |
| const valTable = document.getElementById('validatorsTable'); | |
| validators.forEach(v => { | |
| const row = ` | |
| <tr style="border-bottom:1px solid rgba(255,255,255,0.05);"> | |
| <td style="padding:15px;">${v.name}</td> | |
| <td>${v.stake} ARC</td> | |
| <td style="color:var(--success);"><i class="fa-solid fa-circle" style="font-size:0.5rem"></i> ${v.status}</td> | |
| <td>${v.blocks}</td> | |
| </tr> | |
| `; | |
| valTable.innerHTML += row; | |
| }); | |
| // --- Auto Generate Blocks --- | |
| setInterval(() => { | |
| createBlock(); | |
| }, 5000); | |
| // --- P2P Canvas Visualization --- | |
| let canvas, ctx, nodes = []; | |
| function initNetworkVis() { | |
| canvas = document.getElementById('networkCanvas'); | |
| ctx = canvas.getContext('2d'); | |
| canvas.width = canvas.parentElement.offsetWidth; | |
| canvas.height = 300; | |
| nodes = []; | |
| for(let i=0; i<20; i++) { | |
| nodes.push({ | |
| x: Math.random() * canvas.width, | |
| y: Math.random() * canvas.height, | |
| vx: (Math.random() - 0.5) * 2, | |
| vy: (Math.random() - 0.5) * 2 | |
| }); | |
| } | |
| animateNetwork(); | |
| } | |
| function animateNetwork() { | |
| if(!document.getElementById('network').classList.contains('active')) return; | |
| ctx.fillStyle = '#000'; | |
| ctx.fillRect(0, 0, canvas.width, canvas.height); | |
| // Draw Connections | |
| ctx.strokeStyle = 'rgba(0, 242, 234, 0.2)'; | |
| ctx.lineWidth = 1; | |
| for(let i=0; i<nodes.length; i++) { | |
| for(let j=i+1; j<nodes.length; j++) { | |
| const dx = nodes[i].x - nodes[j].x; | |
| const dy = nodes[i].y - nodes[j].y; | |
| const dist = Math.sqrt(dx*dx + dy*dy); | |
| if(dist < 100) { | |
| ctx.beginPath(); | |
| ctx.moveTo(nodes[i].x, nodes[i].y); | |
| ctx.lineTo(nodes[j].x, nodes[j].y); | |
| ctx.stroke(); | |
| } | |
| } | |
| } | |
| // Draw Nodes | |
| nodes.forEach(node => { | |
| node.x += node.vx; | |
| node.y += node.vy; | |
| if(node.x < 0 || node.x > canvas.width) node.vx *= -1; | |
| if(node.y < 0 || node.y > canvas.height) node.vy *= -1; | |
| ctx.fillStyle = '#00f2ea'; | |
| ctx.beginPath(); | |
| ctx.arc(node.x, node.y, 3, 0, Math.PI*2); | |
| ctx.fill(); | |
| }); | |
| requestAnimationFrame(animateNetwork); | |
| } | |
| // Initialize first block | |
| createBlock(); | |
| // Mock Wallet Address | |
| document.getElementById('myAddress').innerText = '0x' + Array(40).fill(0).map(() => Math.floor(Math.random() * 16).toString(16)).join(''); | |
| </script> | |
| </body> | |
| </html> |