ChainVigil
Features Live Demo Pricing Launch App →
Live Scanning 5 Chains — Ethereum, Base, Arbitrum, Solana, Bitcoin

Onchain Portfolio
Security & Alpha

Monitor any wallet in real-time. Get Telegram alerts before you get rugged. Track alpha — not just balances.

Try It Now — Scan Any Wallet

Free to try. No credit card needed.

Pre-filled: Vitalik's wallet — click Scan to see it live

What ChainVigil Does

Deep Wallet Scanner

Scan any address across 5 chains. See every token, balance, USD value, and risk flags in seconds.

Portfolio Security Alerts

Get Telegram alerts when wallet values change significantly or new risky tokens appear.

Alpha Score

Smart money analysis — wallets with high alpha show accumulation of quality tokens at low prices.

Rug Pull Detection

Instantly audit any token for honeypots, mintable supply, owner privileges and more.

Portfolio History

Track your tracked wallets' value over time. See growth, spot patterns.

Multi-Chain

One dashboard for Ethereum, Base, Arbitrum, Solana, and Bitcoin.

Rug Pull Detector

Paste any contract address to check for honeypots, mint functions, and owner risks.

Pricing

Beta — Limited Access
$29/mo
  • Track up to 10 wallets
  • Multi-chain (5 chains)
  • Real-time security alerts
  • Alpha Score analysis
  • Telegram bot integration
  • Portfolio history
Get Early Access →
Free
$0
  • Scan any wallet (public)
  • Token audit (limited)
  • 3 tracked wallets
  • No portfolio history
  • No security alerts
Sign Up Free →

Live Alpha Intelligence

Real-time multi-chain smart money analysis. Updated every 2 hours.

Network Token Alpha Score
Loading alpha scores...

6 chains monitored: Ethereum, Base, Arbitrum, BSC, Polygon, Optimism

DeFi Protocol Safety

Data-backed safety scores for top DeFi protocols. Grade A-F based on audit status, TVL stability, and smart money adoption.

Protocol Category TVL Grade Security Adoption Chains
Loading protocol safety scores...

Smart Money Intelligence

23 whales and institutions tracked across Ethereum.

Events Tracked
Wallets Monitored
Unique Tokens
Loading smart money events...

Start tracking wallets — free

Create an account in 10 seconds. Track up to 3 wallets.

Powered by Alchemy End-to-end encrypted 6 chains monitored
\n const API = '/api/v1'; // Mobile menu function toggleMobileMenu() { const menu = document.getElementById('mobile-menu'); const icon = document.getElementById('menu-icon'); menu.classList.toggle('open'); if (menu.classList.contains('open')) { icon.setAttribute('data-lucide', 'x'); } else { icon.setAttribute('data-lucide', 'menu'); } lucide.createIcons(); } function closeMobileMenu() { const menu = document.getElementById('mobile-menu'); const icon = document.getElementById('menu-icon'); menu.classList.remove('open'); icon.setAttribute('data-lucide', 'menu'); lucide.createIcons(); } // Toast notifications function showToast(message, type = 'info') { const container = document.getElementById('toast-container'); const toast = document.createElement('div'); toast.className = `toast toast-${type}`; const icons = { error: 'alert-triangle', success: 'check-circle', info: 'info' }; const icon = icons[type] || icons.info; toast.innerHTML = `
${message}
`; container.appendChild(toast); lucide.createIcons(); setTimeout(() => { toast.style.opacity = '0'; toast.style.transform = 'translateX(1rem)'; toast.style.transition = 'all 0.3s ease'; setTimeout(() => toast.remove(), 300); }, 4000); } // Format error messages function formatError(err, fallback) { if (err.message && err.message.includes('Failed to fetch')) return 'Unable to connect to ChainVigil servers. Please check your internet connection and try again.'; if (err.message) return err.message; return fallback || 'An unexpected error occurred. Please try again.'; } // Market ticker async function fetchTicker() { const el = document.getElementById('market-ticker'); try { const r = await fetch('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum,solana,chainlink,uniswap,arbitrum&vs_currencies=usd&include_24hr_change=true'); if (!r.ok) throw new Error('API unavailable'); const d = await r.json(); let h = ''; for (const [c,v] of Object.entries(d)) { const ch = (v.usd_24h_change||0).toFixed(2); const col = ch >= 0 ? 'text-emerald-400' : 'text-red-400'; const arrow = ch >= 0 ? '▲' : '▼'; h += `${c.toUpperCase()} $${v.usd.toLocaleString()} ${arrow} ${ch}%`; } el.innerHTML = h + h; } catch(e) { // Keep existing content or show subtle fallback if (!el.querySelector('.ticker span') || el.querySelector('.skeleton')) { el.innerHTML = 'Market data temporarily unavailable'; } } } fetchTicker(); setInterval(fetchTicker, 60000); // Demo wallet scan async function demoScan(e) { e.preventDefault(); const addr = document.getElementById('demo-addr').value.trim(); const chain = document.getElementById('demo-chain').value; const btn = document.getElementById('demo-btn'); const results = document.getElementById('demo-results'); const errorEl = document.getElementById('demo-error'); // Validate if (!addr || !addr.match(/^0x[0-9a-fA-F]{40}$/)) { errorEl.classList.remove('hidden'); errorEl.textContent = 'Please enter a valid Ethereum address (0x followed by 40 hex characters).'; return; } errorEl.classList.add('hidden'); btn.textContent = 'Scanning...'; btn.disabled = true; results.classList.remove('hidden'); results.innerHTML = '
'; try { const r = await fetch(`${API}/wallet/${addr}?network=${chain}`); if (!r.ok) { const d = await r.json().catch(() => ({})); throw new Error(d.error || `Server responded with ${r.status}`); } const d = await r.json(); if (d.error) throw new Error(d.error); results.innerHTML = `
Native
${(d.native_balance||0).toFixed(4)} ${d.native_symbol||''}
Total Value
$${(d.total_value_usd||0).toFixed(2)}
Tokens
${(d.tokens||[]).length}
${(d.tokens||[]).slice(0, 10).map(t => `
${(t.risk_level||'unknown').toUpperCase()} ${(t.symbol||'Unknown')} ${(t.name||'').substring(0,20)}
${(t.balance||0).toFixed(4)}
$${(t.value_usd||0).toFixed(2)}
`).join('')}
`; } catch(e) { results.innerHTML = ''; errorEl.classList.remove('hidden'); errorEl.textContent = formatError(e, 'Scan failed. Please try again.'); } btn.textContent = 'Scan →'; btn.disabled = false; } // Token audit async function auditToken(e) { e.preventDefault(); const addr = document.getElementById('audit-addr').value.trim(); const chain = document.getElementById('audit-chain').value; const btn = document.getElementById('audit-btn'); const results = document.getElementById('audit-results'); const errorEl = document.getElementById('audit-error'); if (!addr || !addr.match(/^0x[0-9a-fA-F]{40}$/)) { errorEl.classList.remove('hidden'); errorEl.textContent = 'Please enter a valid contract address.'; return; } errorEl.classList.add('hidden'); btn.textContent = 'Auditing...'; btn.disabled = true; results.classList.remove('hidden'); results.innerHTML = '
'; try { const r = await fetch(`${API}/token/check`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ address: addr, network: chain }) }); const d = await r.json(); if (d.error) throw new Error(d.error); const flags = d.flags || []; const risk = (d.risk || 'safe').toLowerCase(); const riskLabel = risk.charAt(0).toUpperCase() + risk.slice(1); const riskColor = risk === 'danger' ? 'text-red-400' : risk === 'warning' ? 'text-yellow-400' : 'text-[var(--accent)]'; let flagsHtml = ''; for (const flag of flags) { const label = flag.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()); flagsHtml += `
${label}
`; } if (!flagsHtml) { flagsHtml = '
No issues detected
'; } results.innerHTML = `
Risk Level
${riskLabel}
Contract
${(d.contract||addr).substring(0,10)}...${(d.contract||addr).substring(38)}
Flags
${flags.length}
${flagsHtml}
`; } catch(e) { results.innerHTML = ''; errorEl.classList.remove('hidden'); errorEl.textContent = formatError(e, 'Audit failed. Please try again.'); } btn.textContent = 'Audit →'; btn.disabled = false; } // ======================================== // LIVE ALPHA INTELLIGENCE // ======================================== async function fetchAlphaTable() { const tbody = document.getElementById('alpha-table-body'); if (!tbody) return; try { const r = await fetch(`${API}/alpha/public`); if (!r.ok) throw new Error('Alpha fetch failed'); const d = await r.json(); const tokens = d.tokens || []; if (!tokens.length) { tbody.innerHTML = 'No alpha data available yet'; return; } // Filter out stablecoins and wrapped tokens - they have no alpha const STABLECOINS = new Set(['USDT','USDC','DAI','BUSD','USDP','TUSD','USDD','FRAX','LUSD','GUSD','USDN','FEI','sUSD','USDE']); const WRAPPED = new Set(['WETH','WBNB','WBTC','WMATIC','WPOL','WAVAX','WFTM','WONE','WGLMR']); const filtered = tokens.filter(t => { const sym = (t.symbol || '').toUpperCase(); return !STABLECOINS.has(sym) && !WRAPPED.has(sym) && (t.liquidity_usd || 0) >= 50000; }); // Sort by score desc, show top 15 const sorted = filtered.sort((a, b) => (b.score || 0) - (a.score || 0)).slice(0, 15); const FREE_ROWS = 3; let html = ''; for (let i = 0; i < sorted.length; i++) { const t = sorted[i]; const isFree = i < FREE_ROWS; const score = t.score || 0; const scoreColor = score >= 70 ? 'text-[var(--accent)]' : score >= 40 ? 'text-yellow-400' : 'text-red-400'; const net = (t.network || 'ethereum').charAt(0).toUpperCase() + (t.network || 'ethereum').slice(1); const liq = (t.liquidity_usd && t.liquidity_usd >= 50000) ? `$${(t.liquidity_usd / 1e6).toFixed(1)}M` : '—'; const priceVal = t.price_change_24h; const price = (priceVal && priceVal >= 0.01) ? `$${Number(priceVal).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})}` : '—'; const ratio = t.components?.buy_sell_momentum?.ratio_6h; const ratioStr = ratio ? ratio.toFixed(2) : '—'; if (isFree) { html += ` ${net} ${t.symbol || '—'} ${score.toFixed(0)} ${price} ${ratioStr} ${liq} `; } else if (i === FREE_ROWS) { // Blur row with CTA html += ` ●●●●● ■■ $■■■ ■.■■ $■■■M `; } } // CTA row: "Sign up to see all ${N} tokens" const hiddenCount = sorted.length - FREE_ROWS; html += ` Unlock all ${sorted.length} alpha scores — Sign up free `; tbody.innerHTML = html; } catch(e) { tbody.innerHTML = 'Failed to load alpha scores'; } } // ======================================== // DEFI PROTOCOL SAFETY // ======================================== async function fetchDefiProtocols() { const tbody = document.getElementById('defi-table-body'); if (!tbody) return; try { const r = await fetch(`${API}/protocols/public`); if (!r.ok) throw new Error('Protocol fetch failed'); const d = await r.json(); const protocols = d.protocols || []; if (!protocols.length) { tbody.innerHTML = 'No protocol data available'; return; } // Sort by grade, then TVL const gradeOrder = { A: 5, B: 4, C: 3, D: 2, F: 1 }; const sorted = protocols.sort((a, b) => (gradeOrder[b.grade || 'F'] || 0) - (gradeOrder[a.grade || 'F'] || 0)); let html = ''; for (const p of sorted) { const tvlUsd = p.tvl_usd || 0; const tvl = tvlUsd >= 1e9 ? `$${(tvlUsd / 1e9).toFixed(2)}B` : tvlUsd >= 1e6 ? `$${(tvlUsd / 1e6).toFixed(0)}M` : '—'; const gradeColor = { A: 'bg-emerald-500/20 text-emerald-400', B: 'bg-blue-500/20 text-blue-400', C: 'bg-yellow-500/20 text-yellow-400', D: 'bg-orange-500/20 text-orange-400', F: 'bg-red-500/20 text-red-400' }; const chainCount = p.chain_addresses ? Object.keys(p.chain_addresses).length : (p.chains ? p.chains.length : 0); html += ` ${p.protocol || '—'} ${p.category || '—'} ${tvl} ${p.grade || '—'} ${(p.security_score||0).toFixed(0)} ${(p.adoption_score||0).toFixed(0)} ${chainCount} `; } tbody.innerHTML = html; } catch(e) { tbody.innerHTML = 'Failed to load protocol data'; } } // ======================================== // SMART MONEY INTELLIGENCE // ======================================== async function fetchSmartMoney() { // Stats try { const r = await fetch(`${API}/smart-money/stats`); if (r.ok) { const s = await r.json(); const eventsEl = document.getElementById('sm-total-events'); const walletsEl = document.getElementById('sm-unique-wallets'); const tokensEl = document.getElementById('sm-unique-tokens'); const countEl = document.getElementById('sm-event-count'); if (eventsEl) eventsEl.textContent = s.total_events != null ? Number(s.total_events).toLocaleString() : '—'; if (walletsEl) walletsEl.textContent = s.unique_wallets != null ? Number(s.unique_wallets).toLocaleString() : '—'; if (tokensEl) tokensEl.textContent = s.unique_tokens != null ? Number(s.unique_tokens).toLocaleString() : '—'; if (countEl) countEl.textContent = s.total_events != null ? `(${Number(s.total_events).toLocaleString()} events tracked)` : ''; // Also update the headline whale count if smart_money_users exists } } catch(e) { console.warn('Smart money stats failed:', e); } // Recent events try { const r = await fetch(`${API}/smart-money/events`); if (r.ok) { const d = await r.json(); const events = d.events || []; const container = document.getElementById('sm-recent-events'); if (!container) return; if (!events.length) { container.innerHTML = '
No recent events
'; return; } // Show latest 5 free, blur rest const FREE_EVENTS = 5; const recent = events.slice(0, 12); let html = ''; for (let i = 0; i < recent.length; i++) { const ev = recent[i]; const isFree = i < FREE_EVENTS; if (isFree) { const typeLabel = ev.event_type === 'new_holding' ? 'NEW' : ev.event_type === 'sell' ? 'SELL' : ev.event_type || 'UNKNOWN'; const typeColor = ev.event_type === 'new_holding' ? 'bg-[var(--accent)]/10 text-[var(--accent)]' : ev.event_type === 'sell' ? 'bg-red-500/10 text-red-400' : 'bg-gray-500/10 text-gray-400'; const label = ev.wallet_label || ev.wallet_address ? ev.wallet_address.substring(0, 10) + '...' : 'Unknown'; html += `
${typeLabel}
${ev.token_symbol || '?'} (${ev.chain || 'eth'})
${label}
`; } else if (i === FREE_EVENTS) { html += `
+${recent.length - FREE_EVENTS} more events hidden
Sign up to see all smart money
`; break; } } container.innerHTML = html; } } catch(e) { console.warn('Smart money events failed:', e); } } // ======================================== // INITIALIZE // ======================================== fetchAlphaTable(); fetchDefiProtocols(); fetchSmartMoney(); // Refresh every 5 minutes setInterval(fetchAlphaTable, 300000); setInterval(fetchDefiProtocols, 600000); setInterval(fetchSmartMoney, 300000);