Spaces:
Running
Running
File size: 7,249 Bytes
58c926b 22b90b1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Wallet Balance – Demo UI</title>
<style>
:root{
--bg:#0f1220;--card:#171a2b;--text:#e7e9f3;--muted:#a7adc2;--accent:#6d8dff;--accent-2:#9b6dff;--danger:#ff6d6d;--ok:#60d394;
--border:rgba(255,255,255,.08);--shadow:0 10px 30px rgba(0,0,0,.35);
}
*{box-sizing:border-box} body{margin:0;background:radial-gradient(1200px 600px at 10% -10%, #1e2240 0%, #0f1220 60%), #0f1220;color:var(--text);font:16px/1.4 system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif}
.container{max-width:900px;margin:40px auto;padding:16px}
.banner{background:linear-gradient(90deg,rgba(255,255,255,.06),rgba(255,255,255,.02));border:1px solid var(--border);padding:12px 14px;border-radius:14px;margin-bottom:16px}
.banner strong{color:var(--ok)}
.row{display:grid;grid-template-columns:1.2fr .8fr auto;gap:10px}
.card{background:linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.02));border:1px solid var(--border);border-radius:20px;box-shadow:var(--shadow);padding:18px}
.title{font-size:24px;font-weight:700;margin:2px 0 14px}
label{display:block;font-size:12px;color:var(--muted);margin-bottom:6px}
input,select,button{width:100%;border-radius:14px;border:1px solid var(--border);padding:12px 14px;background:#0f1220;color:var(--text)}
input:focus,select:focus,button:focus{outline:2px solid color-mix(in oklab, var(--accent) 60%, white)}
button{cursor:pointer;background:linear-gradient(135deg, var(--accent), var(--accent-2));border:none;font-weight:700}
button[disabled]{opacity:.6;cursor:not-allowed}
.muted{color:var(--muted)}
.result{display:none;margin-top:14px;border-top:1px dashed var(--border);padding-top:14px}
.result.visible{display:block}
.pill{display:inline-flex;gap:8px;align-items:center;border:1px solid var(--border);padding:6px 10px;border-radius:999px;background:rgba(255,255,255,.04);font-size:12px}
.grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.footer{margin-top:30px;color:var(--muted);font-size:12px;text-align:center}
.error{color:var(--danger);font-size:13px;margin-top:8px}
.copy{background:transparent;border:1px dashed var(--border);padding:8px 12px}
@media (max-width:800px){.row{grid-template-columns:1fr}}
</style>
</head>
<body>
<div class="container">
<div class="banner">
<strong>Demo only:</strong> This page is a front‑end example. It does <em>not</em> query a real blockchain or wallet provider. Replace the mock code with your own API calls if you are building a legitimate balance checker.
</div>
<div class="card">
<div class="title">Wallet Balance</div>
<div class="row">
<div>
<label for="address">Wallet Address</label>
<input id="address" placeholder="0x… or other format" autocomplete="off" />
</div>
<div>
<label for="network">Network</label>
<select id="network">
<option value="ethereum" selected>Ethereum</option>
<option value="bsc">BNB Smart Chain</option>
<option value="solana">Solana</option>
<option value="polygon">Polygon</option>
<option value="tron">TRON</option>
</select>
</div>
<div style="align-self:end">
<button id="checkBtn">Check Balance</button>
</div>
</div>
<div class="error" id="error"></div>
<div class="result" id="result">
<div class="grid">
<div>
<div class="muted">Normalized Balance</div>
<div id="balance" style="font-size:28px;font-weight:800;">—</div>
</div>
<div>
<div class="muted">Address</div>
<div style="display:flex;gap:8px;align-items:center">
<code id="addrOut" style="font-size:12px;opacity:.9"></code>
<button class="pill copy" id="copyBtn" title="Copy address">Copy</button>
</div>
</div>
</div>
<div style="margin-top:10px" class="muted" id="note"></div>
</div>
</div>
<div class="footer">
<p>For production, use official SDKs/APIs (e.g., Alchemy, Infura, QuickNode, Solana RPC), validate inputs, and never misrepresent balances or brands.</p>
</div>
</div>
<script>
// --- Simple deterministic mock so results are stable for the same input ---
function hashToNumber(str){
let h1 = 0xdeadbeef ^ str.length, h2 = 0x41c6ce57 ^ str.length;
for (let i=0; i<str.length; i++){
const ch = str.charCodeAt(i);
h1 = Math.imul(h1 ^ ch, 2654435761);
h2 = Math.imul(h2 ^ ch, 1597334677);
}
h1 = (h1 ^ (h1>>>16)) >>> 0; h2 = (h2 ^ (h2>>>13)) >>> 0;
return (h1 + h2) >>> 0; // 0..2^32-1
}
function format(num){
return new Intl.NumberFormat(undefined, {maximumFractionDigits:6}).format(num);
}
const address = document.getElementById('address');
const network = document.getElementById('network');
const btn = document.getElementById('checkBtn');
const error = document.getElementById('error');
const result = document.getElementById('result');
const balanceEl = document.getElementById('balance');
const addrOut = document.getElementById('addrOut');
const note = document.getElementById('note');
const copyBtn = document.getElementById('copyBtn');
function validate(addr){
if (!addr || addr.trim().length < 6) return 'Enter a valid address.';
// Very light checks – expand per network as needed
if (network.value === 'ethereum' || network.value === 'bsc' || network.value === 'polygon'){
if (!/^0x[0-9a-fA-F]{6,}$/.test(addr)) return 'Expected an 0x… style address for this network.';
}
return '';
}
btn.addEventListener('click', () => {
error.textContent = '';
result.classList.remove('visible');
const addr = address.value.trim();
const v = validate(addr);
if (v){ error.textContent = v; return; }
btn.disabled = true; btn.textContent = 'Checking…';
// Simulate delay
setTimeout(() => {
const seed = hashToNumber(addr + '|' + network.value);
const base = (seed % 10_000_000) / 100_000; // up to 100
const decimals = network.value === 'solana' || network.value === 'tron' ? 2 : 4;
const displayed = Number(base.toFixed(decimals));
balanceEl.textContent = format(displayed);
addrOut.textContent = addr;
note.textContent = `Mock value based on input • Network: ${network.options[network.selectedIndex].text}`;
result.classList.add('visible');
btn.disabled = false; btn.textContent = 'Check Balance';
}, 500);
});
copyBtn.addEventListener('click', async () => {
const text = addrOut.textContent || '';
if (!text) return;
try { await navigator.clipboard.writeText(text); copyBtn.textContent = 'Copied'; setTimeout(()=>copyBtn.textContent='Copy', 1200);} catch(e){ console.warn(e); }
});
</script>
</body>
</html> |