SPB Git

spb/coinexplorer Public MIT

Self-hosted, zero-API-key explorer for stablecoins and major crypto.

Python 60.3% HTML 23.6% JavaScript 8.1% CSS 6.8% SQL 1%
3.5 KB · 78 lines html
Raw Blame History
1<!doctype html>2<!-- Author: Simon-Pierre Boucher -->3<!-- Mail: contact@spboucher.ai -->4<html lang="en">5<head>6<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">7<title>whales — coinexplorer</title>8<link rel="stylesheet" href="/assets/style.css">9</head>10<body>11<main>12  <div class="pagehead"><h1>Whale watch</h1>13    <span class="sub">largest stablecoin & crypto movements across all indexed chains — including native BTC / ETH / SOL / TRX / BNB whales</span></div>1415  <div class="filters">16    <select id="tokenSel"><option value="">all tokens</option></select>17    <select id="minSel">18      <option value="250000">≥ $250K</option>19      <option value="1000000" selected>≥ $1M</option>20      <option value="10000000">≥ $10M</option>21      <option value="100000000">≥ $100M</option>22    </select>23    <div class="presets" role="group" aria-label="Window">24      <button data-w="1h">1h</button><button data-w="24h" aria-pressed="true">24h</button><button data-w="7d">7d</button>25    </div>26  </div>2728  <section class="card tile"><h2>Transfers over threshold</h2>29    <div class="big" id="tCount">—</div><div class="note" id="tCountN"></div></section>30  <section class="card tile"><h2>Combined value</h2>31    <div class="big" id="tSum">—</div><div class="note">sum of listed transfers</div></section>32  <section class="card half"><h2>By chain</h2><div class="bars" id="chainBars"></div></section>3334  <section class="card"><h2>Transfers</h2>35    <div class="scroll" style="max-height:65vh"><table>36      <thead><tr><th>chain</th><th>token</th><th class="num">USD</th><th>from</th><th>to</th><th>tx</th><th>when</th></tr></thead>37      <tbody id="rows"></tbody></table></div></section>38</main>3940<script type="module">41import { $, j, fmtUsd, fmtN, mountNav, hbars, addrLink, txLink, chainLink, tokenLink, ago } from "/assets/app.js";42mountNav("Whales");43let WINDOW = "24h";4445async function load() {46  const tok = $("tokenSel").value, min = $("minSel").value;47  const url = `/v1/stablecoins/whales?window=${WINDOW}&min_usd=${min}&limit=200` + (tok ? `&token=${tok}` : "");48  const rows = await j(url);49  $("tCount").textContent = fmtN(rows.length);50  $("tCountN").textContent = `≥ ${fmtUsd(+min)} · last ${WINDOW}`;51  $("tSum").textContent = fmtUsd(rows.reduce((a, r) => a + r.usd, 0));52  const byChain = {};53  for (const r of rows) byChain[r.chain] = (byChain[r.chain] || 0) + r.usd;54  hbars($("chainBars"), Object.entries(byChain)55    .map(([k, v]) => ({ k, v, link: chainLink(k) })).sort((a, b) => b.v - a.v).slice(0, 8));56  $("rows").innerHTML = rows.map((x) =>57    `<tr><td>${chainLink(x.chain)}</td><td>${tokenLink(x.symbol)}</td>58     <td class="num"><b>${fmtUsd(x.usd)}</b></td><td>${addrLink(x.from)}</td>59     <td>${addrLink(x.to)}</td><td>${txLink(x.chain, x.tx_hash)}</td>60     <td>${ago(x.timestamp)} ago</td></tr>`).join("") ||61    `<tr><td colspan="7" class="empty">none in window</td></tr>`;62}6364j("/v1/tokens").then((t) => {65  $("tokenSel").innerHTML = `<option value="">all tokens</option>` +66    Object.keys(t).sort().map((s) => `<option>${s}</option>`).join("");67});68["tokenSel", "minSel"].forEach((id) => $(id).addEventListener("change", load));69document.querySelectorAll(".presets button").forEach((b) => b.addEventListener("click", () => {70  document.querySelectorAll(".presets button").forEach((x) => x.setAttribute("aria-pressed", "false"));71  b.setAttribute("aria-pressed", "true"); WINDOW = b.dataset.w; load();72}));73load();74setInterval(load, 60_000);75</script>76</body>77</html>78