Loading blockchain data...
{{ error }}
Current Height
{{ formatNumber(chainInfo.height) }}
Latest Block
{{ formatHash(chainInfo.hash) }}
Total Transactions
{{ formatNumber(stats.totalTransactions) }}
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js' const API_BASE = '/api/v1' const app = createApp({ data() { return { loading: true, chainInfo: { height: 0, hash: '', timestamp: null, tx_count: 0 }, latestBlocks: [], stats: { totalBlocks: 0, totalTransactions: 0, avgBlockTime: 2.0, hashRate: '0 H/s' }, error: null } }, async mounted() { await this.loadChainData() setInterval(this.loadChainData, 5000) }, methods: { async loadChainData() { try { this.error = null // Load chain head const headResponse = await fetch(`${API_BASE}/chain/head`) if (headResponse.ok) { this.chainInfo = await headResponse.json() } // Load latest blocks const blocksResponse = await fetch(`${API_BASE}/chain/blocks?limit=10`) if (blocksResponse.ok) { this.latestBlocks = await blocksResponse.json() } // Calculate stats this.stats.totalBlocks = this.chainInfo.height || 0 this.stats.totalTransactions = this.latestBlocks.reduce((sum, block) => sum + (block.tx_count || 0), 0) this.loading = false } catch (error) { console.error('Failed to load chain data:', error) this.error = 'Failed to connect to blockchain node' this.loading = false } }, formatHash(hash) { if (!hash) return '-' return hash.substring(0, 10) + '...' + hash.substring(hash.length - 8) }, formatTime(timestamp) { if (!timestamp) return '-' return new Date(timestamp * 1000).toLocaleString() }, formatNumber(num) { if (!num) return '0' return num.toLocaleString() }, getBlockType(block) { if (!block) return 'unknown' return block.tx_count > 0 ? 'with-tx' : 'empty' } }, template: `
Loading blockchain data...
{{ error }}
{{ formatNumber(chainInfo.height) }}
{{ formatHash(chainInfo.hash) }}
{{ formatNumber(stats.totalTransactions) }}