doge_wallet_explorer / index.html
offerpk3's picture
Update index.html
0a49e78 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MyDoge Wallet Explorer</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.nft-card {
transition: all 0.3s ease;
}
.nft-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}
.doge-pattern {
background-color: #f8fafc;
background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23c6bebe' fill-opacity='0.2'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}
.skeleton-loader {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.spinner {
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body class="doge-pattern min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-6xl">
<!-- Header -->
<header class="text-center mb-12">
<div class="flex items-center justify-center mb-4">
<i class="fab fa-dochub text-amber-500 text-5xl mr-3"></i>
<h1 class="text-4xl font-bold text-gray-800">MyDoge Wallet Explorer</h1>
</div>
<p class="text-gray-600 max-w-2xl mx-auto">
Explore Dogecoin wallet balances, transaction history, and associated NFTs in one place.
</p>
</header>
<!-- Search Section -->
<div class="bg-white rounded-xl shadow-lg p-6 mb-8">
<div class="flex flex-col md:flex-row gap-4">
<div class="flex-grow">
<label for="dogeAddress" class="block text-sm font-medium text-gray-700 mb-1">
Dogecoin Wallet Address
</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i class="fas fa-wallet text-gray-400"></i>
</div>
<input
type="text"
id="dogeAddress"
placeholder="D8v4f5kS1CKMZCgD8qt7dZ9eWdNd..."
class="pl-10 block w-full rounded-md border-gray-300 shadow-sm focus:border-amber-500 focus:ring focus:ring-amber-200 focus:ring-opacity-50 py-3 px-4 border"
>
</div>
</div>
<div class="flex items-end">
<button
onclick="fetchWalletData()"
class="bg-amber-500 hover:bg-amber-600 text-white font-bold py-3 px-6 rounded-md transition duration-300 flex items-center"
id="search-btn"
>
<i class="fas fa-search mr-2"></i> Explore Wallet
</button>
</div>
</div>
</div>
<!-- Wallet Info Section -->
<div id="wallet-info" class="bg-white rounded-xl shadow-lg p-6">
<!-- Loading State -->
<div id="loading-state" class="hidden">
<div class="flex flex-col items-center py-8">
<div class="w-16 h-16 rounded-full border-4 border-amber-500 border-t-transparent spinner mb-4"></div>
<p class="text-gray-600">Fetching wallet data...</p>
</div>
</div>
<!-- Error State -->
<div id="error-state" class="hidden bg-red-50 border-l-4 border-red-500 p-4 mb-6">
<div class="flex">
<div class="flex-shrink-0">
<i class="fas fa-exclamation-circle text-red-500"></i>
</div>
<div class="ml-3">
<p id="error-message" class="text-sm text-red-700"></p>
</div>
</div>
</div>
<!-- Balance Section -->
<div id="balance-section" class="mb-8">
<h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-coins text-amber-500 mr-2"></i> Wallet Balance
</h2>
<div class="bg-amber-50 rounded-lg p-6">
<div class="flex items-center justify-between">
<div>
<p class="text-sm text-gray-600">Current Balance</p>
<p id="balance" class="text-3xl font-bold text-gray-800">-- DOGE</p>
</div>
<div class="bg-amber-100 p-3 rounded-full">
<i class="fas fa-dog text-amber-600 text-2xl"></i>
</div>
</div>
<div class="mt-4 grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="bg-white p-4 rounded-lg shadow">
<p class="text-sm text-gray-600">Estimated USD Value</p>
<p id="usd-value" class="text-lg font-semibold">--</p>
</div>
<div class="bg-white p-4 rounded-lg shadow">
<p class="text-sm text-gray-600">Transactions</p>
<p id="tx-count" class="text-lg font-semibold">--</p>
</div>
<div class="bg-white p-4 rounded-lg shadow">
<p class="text-sm text-gray-600">First Transaction</p>
<p id="first-tx" class="text-lg font-semibold">--</p>
</div>
</div>
</div>
</div>
<!-- Transaction History -->
<div id="transaction-section" class="mb-8">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-gray-800 flex items-center">
<i class="fas fa-exchange-alt text-amber-500 mr-2"></i> Recent Transactions
</h2>
<button id="view-all-tx" class="text-sm text-amber-600 hover:text-amber-700 hidden">
View All <i class="fas fa-arrow-right ml-1"></i>
</button>
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Tx ID</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Amount</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
</tr>
</thead>
<tbody id="transactions" class="bg-white divide-y divide-gray-200">
<tr>
<td colspan="4" class="px-6 py-4 text-center text-gray-500">Enter a Dogecoin address to view transactions</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- NFTs Section -->
<div id="nft-section">
<h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-image text-amber-500 mr-2"></i> NFT Collection
</h2>
<div id="nft-placeholder" class="text-center py-8">
<i class="fas fa-images text-gray-300 text-5xl mb-4"></i>
<p class="text-gray-500">No NFTs found for this wallet</p>
</div>
<div id="nfts" class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4 hidden">
<!-- NFT cards will be inserted here -->
</div>
</div>
</div>
<!-- Footer -->
<footer class="mt-12 text-center text-gray-500 text-sm">
<p>© 2023 MyDoge Wallet Explorer. Not affiliated with Dogecoin.</p>
<p class="mt-1">Data provided by Blockchair API</p>
</footer>
</div>
<script>
// Configuration
const config = {
dogeApiUrl: 'https://api.blockchair.com/dogecoin',
dogePriceApiUrl: 'https://api.coingecko.com/api/v3/simple/price?ids=dogecoin&vs_currencies=usd',
nftApiUrl: 'https://deep-index.moralis.io/api/v2',
transactionsLimit: 5
};
// Helper functions
function formatDogeAmount(amount) {
return (amount / 100000000).toFixed(2) + ' DOGE';
}
function formatDate(timestamp) {
const date = new Date(timestamp * 1000);
return date.toLocaleDateString() + ' ' + date.toLocaleTimeString();
}
function shortenTxId(txid) {
return txid.substring(0, 10) + '...' + txid.substring(txid.length - 8);
}
function showError(message) {
document.getElementById('error-message').textContent = message;
document.getElementById('error-state').classList.remove('hidden');
}
function hideError() {
document.getElementById('error-state').classList.add('hidden');
}
function showLoading() {
document.getElementById('loading-state').classList.remove('hidden');
}
function hideLoading() {
document.getElementById('loading-state').classList.add('hidden');
}
function toggleButtonLoading(loading) {
const button = document.getElementById('search-btn');
if (loading) {
button.innerHTML = '<div class="w-4 h-4 border-2 border-white border-t-transparent rounded-full spinner mr-2"></div> Loading...';
button.disabled = true;
} else {
button.innerHTML = '<i class="fas fa-search mr-2"></i> Explore Wallet';
button.disabled = false;
}
}
// Main function to fetch wallet data
async function fetchWalletData() {
const address = document.getElementById('dogeAddress').value.trim();
if (!address) {
showError('Please enter a Dogecoin address.');
return;
}
// Validate address format (basic check)
if (!address.startsWith('D') || address.length < 26 || address.length > 35) {
showError('Please enter a valid Dogecoin address (starts with D, 26-35 chars).');
return;
}
// Reset UI
hideError();
showLoading();
toggleButtonLoading(true);
try {
// Fetch Dogecoin price for USD conversion
let dogePrice = 0;
try {
const priceResponse = await fetch(config.dogePriceApiUrl);
const priceData = await priceResponse.json();
dogePrice = priceData.dogecoin.usd;
} catch (e) {
console.warn('Failed to fetch Dogecoin price:', e);
}
// Fetch wallet balance and transactions
const [balanceResponse, transactionsResponse] = await Promise.all([
fetch(`${config.dogeApiUrl}/dashboards/address/${address}`),
fetch(`${config.dogeApiUrl}/dashboards/address/${address}/transactions?limit=${config.transactionsLimit}`)
]);
if (!balanceResponse.ok || !transactionsResponse.ok) {
throw new Error('Failed to fetch wallet data from Blockchair API');
}
const balanceData = await balanceResponse.json();
const transactionsData = await transactionsResponse.json();
// Process balance data
const walletData = balanceData.data[address];
if (!walletData) {
throw new Error('No data found for this address');
}
const balance = walletData.address.balance;
const txCount = walletData.address.transaction_count;
const firstTxTime = walletData.address.first_seen_receiving;
// Update balance UI
document.getElementById('balance').textContent = formatDogeAmount(balance);
document.getElementById('usd-value').textContent = dogePrice ?
'$' + ((balance / 100000000) * dogePrice).toFixed(2) : 'Price data unavailable';
document.getElementById('tx-count').textContent = txCount;
document.getElementById('first-tx').textContent = firstTxTime ?
formatDate(firstTxTime) : 'Unknown';
// Process transactions
const txTable = document.getElementById('transactions');
txTable.innerHTML = '';
if (transactionsData.data && transactionsData.data.length > 0) {
transactionsData.data.forEach(tx => {
const isIncoming = tx.outputs.some(output => output.recipient === address);
const amount = isIncoming ?
tx.outputs.find(output => output.recipient === address).value :
-tx.inputs.find(input => input.recipient === address).value;
const row = document.createElement('tr');
row.className = 'hover:bg-gray-50';
row.innerHTML = `
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
<a href="https://blockchair.com/dogecoin/transaction/${tx.hash}" target="_blank" class="text-amber-600 hover:text-amber-700">
${shortenTxId(tx.hash)}
</a>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm ${amount < 0 ? 'text-red-500' : 'text-green-500'}">
${formatDogeAmount(Math.abs(amount))}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
${formatDate(tx.time)}
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
Confirmed
</span>
</td>
`;
txTable.appendChild(row);
});
// Show view all button if there are transactions
if (txCount > config.transactionsLimit) {
document.getElementById('view-all-tx').classList.remove('hidden');
document.getElementById('view-all-tx').onclick = () => {
window.open(`https://blockchair.com/dogecoin/address/${address}`, '_blank');
};
}
} else {
const row = document.createElement('tr');
row.innerHTML = `
<td colspan="4" class="px-6 py-4 text-center text-gray-500">
No transactions found for this address
</td>
`;
txTable.appendChild(row);
}
// Try to fetch NFTs (this would require a separate API)
// Note: Dogecoin doesn't natively support NFTs, so this would be for Ethereum NFTs
// associated with the same address (if it exists on Ethereum)
try {
// This is just a placeholder - you would need to implement actual NFT fetching
// based on your requirements and available APIs
document.getElementById('nft-placeholder').classList.remove('hidden');
document.getElementById('nfts').classList.add('hidden');
} catch (e) {
console.warn('Failed to fetch NFTs:', e);
document.getElementById('nft-placeholder').classList.remove('hidden');
document.getElementById('nfts').classList.add('hidden');
}
} catch (error) {
console.error('Error fetching wallet data:', error);
showError(error.message || 'Failed to fetch wallet data. Please try again later.');
} finally {
hideLoading();
toggleButtonLoading(false);
}
}
// Add event listener for Enter key
document.getElementById('dogeAddress').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
fetchWalletData();
}
});
</script>
</body>
</html>