neuromorph-gallery / crypto-script.js
flitrx's picture
Design a neomorphic cryptocurrency tracker website using Web3 with blockchain integration. Make this a fully functional ready to launch website. Provide detailed specifications for user experience, technical architecture, and monetization strategy.
83820df verified
// CryptoSphere - Cryptocurrency Tracker JavaScript
class CryptosphereTracker {
constructor() {
this.web3 = null;
this.provider = null;
this.connectedAccount = null;
this.cryptoData = [];
this.portfolioData = [];
this.currentPage = 1;
this.itemsPerPage = 12;
this.init();
}
async init() {
await this.registerServiceWorker();
this.setupEventListeners();
await this.loadCryptoData();
this.updateMarketStats();
this.setupRealTimeUpdates();
}
// Web3 Wallet Integration
async connectWallet() {
try {
if (window.ethereum) {
this.provider = window.ethereum;
this.web3 = new Web3(this.provider);
// Request account access
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
this.connectedAccount = accounts[0];
this.updateWalletStatus();
await this.loadPortfolioData();
// Listen for account changes
window.ethereum.on('accountsChanged', (accounts) => {
this.connectedAccount = accounts[0] || null;
this.updateWalletStatus();
});
} else {
throw new Error('No Ethereum wallet detected. Please install MetaMask.');
}
} catch (error) {
this.showNotification(error.message, 'error');
}
}
// Real-time Crypto Data from CoinGecko API
async fetchCryptoData(page = 1) {
const vsCurrency = 'usd';
const perPage = this.itemsPerPage;
try {
const response = await fetch(
`https://api.coingecko.com/api/v3/coins/markets?vs_currency=${vsCurrency}&order=market_cap_desc&per_page=${perPage}&page=${page}&sparkline=true&price_change_percentage=24h`
);
if (!response.ok) {
throw new Error('Failed to fetch crypto data');
}
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching crypto data:', error);
return this.getMockCryptoData(page);
}
}
// Mock data for demonstration
getMockCryptoData(page) {
const mockData = [];
const startIndex = (page - 1) * this.itemsPerPage;
const topCryptos = [
{ id: 'bitcoin', symbol: 'btc', name: 'Bitcoin' },
{ id: 'ethereum', symbol: 'eth', name: 'Ethereum' },
{ id: 'binancecoin', symbol: 'bnb', name: 'BNB' },
{ id: 'ripple', symbol: 'xrp', name: 'XRP' },
{ id: 'cardano', symbol: 'ada', name: 'Cardano' },
{ id: 'solana', symbol: 'sol', name: 'Solana' },
{ id: 'polkadot', symbol: 'dot', name: 'Polkadot' }
];
for (let i = 0; i < this.itemsPerPage; i++) {
const crypto = topCryptos[i % topCryptos.length];
const price = Math.random() * 50000 + 1000;
const change24h = (Math.random() - 0.5) * 20;
mockData.push({
id: crypto.id,
symbol: crypto.symbol,
name: crypto.name,
current_price: price,
price_change_percentage_24h: change24h,
market_cap: price * (Math.random() * 1000000),
total_volume: price * (Math.random() * 100000),
price_change_24h: change24h * price / 100,
image: `http://static.photos/finance/200x200/${startIndex + i + 1}`,
sparkline_in_7d: { price: Array(7).fill(0).map(() => price + (Math.random() - 0.5) * 1000
});
}
return mockData;
}
// Load and display crypto data
async loadCryptoData() {
const data = await this.fetchCryptoData(this.currentPage);
this.cryptoData = [...this.cryptoData, ...data];
this.renderCryptoData(data);
}
renderCryptoData(data) {
const grid = document.getElementById('crypto-grid');
data.forEach(crypto => {
const cryptoCard = document.createElement('crypto-card');
cryptoCard.setAttribute('data-crypto', JSON.stringify(crypto));
grid.appendChild(cryptoCard);
});
}
// Update global market statistics
updateMarketStats() {
// Simulate real-time market data updates
setInterval(() => {
const marketCap = (2.1 + Math.random() * 0.1).toFixed(1);
const volume = (78.4 + Math.random() * 5).toFixed(1);
const dominance = (52.3 + (Math.random() - 0.5)).toFixed(1);
document.getElementById('global-market-cap').textContent = `$${marketCap}T`;
document.getElementById('total-volume').textContent = `$${volume}B`;
document.getElementById('btc-dominance').textContent = `${dominance}%`;
}, 3000);
}
// Real-time price updates via WebSocket
setupRealTimeUpdates() {
// This would connect to a WebSocket service for real-time updates
// For demo purposes, we'll simulate with intervals
setInterval(() => {
this.updateLivePrices();
}, 5000);
}
updateLivePrices() {
const cards = document.querySelectorAll('crypto-card');
cards.forEach(card => {
const cryptoData = JSON.parse(card.getAttribute('data-crypto')));
// Simulate price changes
const change = (Math.random() - 0.5) * 2;
const newPrice = cryptoData.current_price * (1 + change / 100);
cryptoData.current_price = newPrice;
cryptoData.price_change_percentage_24h = change;
// Update the card
card.setAttribute('data-crypto', JSON.stringify(cryptoData));
});
}
// Load portfolio data from connected wallet
async loadPortfolioData() {
if (!this.connectedAccount) return;
try {
// In a real implementation, you would query the blockchain
// for the wallet's token holdings and their current values
// Mock portfolio data
this.portfolioData = [
{
id: 'bitcoin',
symbol: 'btc',
name: 'Bitcoin',
amount: Math.random() * 0.5,
value: Math.random() * 15000,
change24h: (Math.random() - 0.5) * 10
},
{
id: 'ethereum',
symbol: 'eth',
name: 'Ethereum',
amount: Math.random() * 10,
value: Math.random() * 20000
}
];
this.renderPortfolio();
} catch (error) {
console.error('Error loading portfolio:', error);
}
}
renderPortfolio() {
const container = document.getElementById('portfolio-container');
if (this.portfolioData.length === 0) {
container.innerHTML = `
<div class="text-center text-gray-400">
<i data-feather="alert-circle" class="w-16 h-16 mx-auto mb-4"></i>
<p>No crypto assets detected in your wallet</p>
`;
} else {
let totalValue = 0;
let totalChange = 0;
const portfolioHTML = this.portfolioData.map(asset => {
totalValue += asset.value;
totalChange += asset.change24h || 0;
return `
<div class="asset ${asset.change24h >= 0 ? 'portfolio-up' : 'portfolio-down'} p-4 mb-4 rounded-xl">
<div class="flex justify-between items-center">
<div class="flex items-center gap-3">
<img src="${asset.image || 'http://static.photos/finance/200x200'}" class="w-10 h-10 rounded-full">
<div>
<div class="font-semibold">${asset.name} (${asset.symbol.toUpperCase()})</div>
<div class="text-right">
<div class="font-bold">$${asset.value.toFixed(2)}</div>
<div class="text-sm ${asset.change24h >= 0 ? 'price-up' : 'price-down'}">
${asset.change24h >= 0 ? '+' : ''}${asset.change24h?.toFixed(2) || '0.00'}%</div>
</div>
</div>
</div>
`;
}).join('');
container.innerHTML = `
<h3 class="text-2xl font-bold text-white mb-6">Your Portfolio</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
${portfolioHTML}
</div>
<div class="mt-6 pt-6 border-t border-gray-600">
<div class="flex justify-between text-xl">
<span>Total Value:</span>
<span class="font-bold text-primary">$${totalValue.toFixed(2)}</div>
`;
}
}
feather.replace();
}
// Event listeners setup
setupEventListeners() {
// Connect wallet button
const connectBtn = document.getElementById('connect-wallet');
if (connectBtn) {
connectBtn.addEventListener('click', () => this.connectWallet());
}
// Load more cryptocurrencies
const loadMoreBtn = document.getElementById('load-more');
if (loadMoreBtn) {
loadMoreBtn.addEventListener('click', () => {
this.currentPage++;
this.loadCryptoData();
});
}
}
// Notification system
showNotification(message, type = 'info') {
const notification = document.createElement('div');
notification.className = `crypto-card p-4 mb-4 ${type === 'error' ? 'border-l-4 border-red-500' : 'border-l-4 border-primary'} crypto-notification`;
notification.innerHTML = `
<div class="flex items-center gap-3">
<i data-feather="${type === 'error' ? 'alert-triangle' : 'check-circle'}`;
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(() => {
notification.remove();
}, 5000);
feather.replace();
}
// Update wallet connection status
updateWalletStatus() {
const connectBtn = document.getElementById('connect-wallet');
if (this.connectedAccount) {
const shortAddress = `${this.connectedAccount.slice(0, 6)}...${this.connectedAccount.slice(-4)}`;
if (connectBtn) {
if (this.connectedAccount) {
connectBtn.innerHTML = `
<i data-feather="user-check" class="inline mr-2"></i>
${this.connectedAccount.slice(0, 6)}...${this.connectedAccount.slice(-4)}`;
} else {
connectBtn.innerHTML = `
<i data-feather="wallet" class="inline mr-2"></i>
${this.connectedAccount.slice(0, 6)}...${this.connectedAccount.slice(-4)}`;
}
}
// PWA Service Worker Registration
async registerServiceWorker() {
if ('serviceWorker' in navigator) {
try {
await navigator.serviceWorker.register('/crypto-sw.js');
console.log('Crypto Service Worker registered successfully');
} catch (error) {
console.error('Crypto Service Worker registration failed:', error);
}
}
}
}
// Initialize the crypto tracker when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
new CryptosphereTracker();
});
// Export for use in other modules
window.CryptosphereTracker = CryptosphereTracker;