koopa-admin-log/configs/exchange-landing/index.html
Hernâni Marques 4ec2f78b14
landings: OG share image + meta include no IBAN badge
Link previews use an updated 1200×630 shop card with the page badge
wording “Intergalactic · GOA · no IBAN”. Meta descriptions/alts match;
?v=noiban cache-busts crawlers that still hold the old image.
2026-07-10 22:28:00 +02:00

583 lines
32 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>GOA Exchange</title>
<meta name="description" content="GOA GNU Taler exchange — withdraw coins, then try GOA shop products on the merchant." />
<link rel="canonical" href="https://exchange.hacktivism.ch/intro/" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="hacktivism.ch · GOA" />
<meta property="og:locale" content="en_US" />
<meta property="og:title" content="GOA Exchange" />
<meta property="og:description" content="GOA exchange for GNU Taler — withdraw coins and explore GOA shop products." />
<meta property="og:url" content="https://exchange.hacktivism.ch/intro/" />
<meta property="og:image" content="https://exchange.hacktivism.ch/intro/og-goa-shop.png?v=noiban" />
<meta property="og:image:secure_url" content="https://exchange.hacktivism.ch/intro/og-goa-shop.png?v=noiban" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="GOA Shop — Intergalactic · GOA · no IBAN — pay with GNU Taler" />
<link rel="image_src" href="https://exchange.hacktivism.ch/intro/og-goa-shop.png?v=noiban" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="GOA Exchange" />
<meta name="twitter:description" content="GOA exchange for GNU Taler — withdraw coins and explore GOA shop products (Intergalactic · GOA · no IBAN)." />
<meta name="twitter:image" content="https://exchange.hacktivism.ch/intro/og-goa-shop.png?v=noiban" />
<meta name="twitter:image:alt" content="GOA Shop — Intergalactic · GOA · no IBAN — pay with GNU Taler" />
<base href="/intro/" />
<style>
:root {
--bg: #1a1410; --card: rgba(42, 32, 24, 0.82); --text: #fff6e8; --muted: #c9b8a0;
--accent2: #3ecfbf; --border: rgba(232, 168, 56, 0.28);
--glow-gold: rgba(232, 168, 56, 0.35); --glow-teal: rgba(62, 207, 191, 0.22);
--val: #f0d090;
}
* { box-sizing: border-box; }
body {
margin: 0; min-height: 100vh;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
color: var(--text); line-height: 1.55; background-color: var(--bg);
background-image:
radial-gradient(ellipse 90% 55% at 50% 108%, rgba(26, 107, 110, 0.55) 0%, transparent 55%),
radial-gradient(circle 420px at 12% 18%, var(--glow-gold) 0%, transparent 62%),
linear-gradient(165deg, #2c1e14 0%, #1a1410 38%, #12181a 72%, #0e1c1e 100%);
background-attachment: fixed;
}
main { max-width: 42rem; margin: 0 auto; padding: 2.25rem 1.25rem 3.5rem; }
.hero { text-align: center; margin: 0 0 1.25rem; }
h1 {
font-size: 1.85rem; font-weight: 750; margin: 0 0 0.45rem;
background: linear-gradient(120deg, #fff6e8 0%, #f0c86a 45%, #3ecfbf 120%);
-webkit-background-clip: text; background-clip: text; color: transparent;
}
.sub { color: var(--muted); max-width: 32rem; margin: 0 auto; }
.badge {
display: inline-block; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.04em;
padding: 0.2rem 0.7rem; border-radius: 999px; margin-bottom: 0.75rem;
border: 1px solid rgba(232, 168, 56, 0.4); color: #f0d090;
background: linear-gradient(135deg, rgba(232, 168, 56, 0.2), rgba(62, 207, 191, 0.15));
}
.stats {
background: rgba(18, 28, 28, 0.55); border: 1px solid rgba(62, 207, 191, 0.28);
border-radius: 16px; padding: 1.1rem 1.15rem; margin: 0 0 1.1rem;
}
.stats h2 {
margin: 0 0 0.35rem; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.12em;
text-transform: uppercase; color: var(--muted); text-align: center;
}
.note { text-align: center; font-size: 0.82rem; color: var(--muted); margin: 0 0 0.9rem; }
.stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.65rem; }
@media (min-width: 420px) { .stats-grid { grid-template-columns: 1fr 1fr 1fr; } }
.stat { background: rgba(0,0,0,0.22); border-radius: 10px; padding: 0.55rem 0.65rem; }
.stat .k { display: block; font-size: 0.68rem; color: var(--muted); text-transform: uppercase; text-align: center; margin-bottom: 0.15rem; letter-spacing: 0.04em; }
.stat .v { display: block; font-size: 1.05rem; font-weight: 750; color: var(--val); text-align: center; font-variant-numeric: tabular-nums; word-break: break-word; }
.stat .v.teal { color: #5eead4; }
.stat .v.sm { font-size: 0.92rem; }
.stats-foot { margin: 0.75rem 0 0; font-size: 0.72rem; color: var(--muted); text-align: center; }
.stats-foot.err { color: #f0a090; }
.stats-run-note {
margin: 0.35rem 0 0; font-size: 0.7rem; color: #f0a090; text-align: center;
}
.sub-block {
margin-top: 0.85rem; padding: 0.75rem 0.85rem;
border-radius: 12px; border: 1px solid rgba(232, 168, 56, 0.22);
background: rgba(0,0,0,0.18);
}
.sub-block h3 {
margin: 0 0 0.5rem; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.1em;
text-transform: uppercase; color: var(--muted); text-align: center;
}
.ladder {
display: flex; flex-wrap: wrap; gap: 0.35rem; justify-content: center;
}
.pill {
font-size: 0.72rem; font-weight: 700; padding: 0.18rem 0.45rem; border-radius: 999px;
border: 1px solid rgba(62, 207, 191, 0.35); color: #99f6e4;
background: rgba(62, 207, 191, 0.1); font-variant-numeric: tabular-nums;
}
.by-denom { font-size: 0.82rem; color: var(--muted); text-align: center; }
.by-denom table { width: 100%; border-collapse: collapse; margin-top: 0.35rem; }
.by-denom th, .by-denom td {
padding: 0.28rem 0.35rem; border-bottom: 1px solid rgba(255,255,255,0.06);
text-align: center; font-variant-numeric: tabular-nums;
}
.by-denom th { color: var(--muted); font-size: 0.68rem; text-transform: uppercase; font-weight: 700; }
.by-denom td { color: var(--val); font-weight: 650; }
.step-card {
background: var(--card); border: 1px solid var(--border); border-radius: 18px;
padding: 1.3rem 1.25rem; margin-bottom: 1.2rem;
}
.step-card h2 { margin: 0 0 0.4rem; text-align: center; font-size: 1.2rem; }
.step-tagline { text-align: center; color: var(--muted); margin: 0 0 1rem; }
.step-body { display: flex; flex-direction: column; align-items: center; gap: 1rem; }
.qr-box { background: #fff; padding: 0.85rem; border-radius: 14px; text-align: center; }
.qr-label { margin-top: 0.5rem; color: #3a342c; font-weight: 700; font-size: 0.85rem; }
.cta {
display: inline-block; text-decoration: none; font-weight: 750; padding: 0.7rem 1.15rem;
border-radius: 12px; background: linear-gradient(135deg, #f0c86a, #c47a18); color: #1a1208;
}
.cta.teal { background: linear-gradient(135deg, #5eead4, #0d9488); color: #042f2e; }
.links { display: flex; flex-direction: column; gap: 0.5rem; width: 100%; }
.cta-sec {
display: block; text-align: center; text-decoration: none; color: var(--accent2);
border: 1px solid rgba(62, 207, 191, 0.4); padding: 0.55rem; border-radius: 10px; font-weight: 600;
}
.meta { font-size: 0.78rem; color: var(--muted); word-break: break-all; text-align: center; }
.app-links {
display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: center; width: 100%;
}
.app-btn {
display: inline-flex; align-items: center; justify-content: center; gap: 0.45rem;
min-width: 9rem; text-decoration: none; font-weight: 700; font-size: 0.88rem;
padding: 0.55rem 0.85rem; border-radius: 10px;
border: 1px solid rgba(232, 168, 56, 0.4); background: rgba(0,0,0,0.28); color: #f0d090;
}
.app-btn.ios { border-color: rgba(232, 168, 56, 0.4); color: #f0d090; }
.app-btn.hub {
flex: 1 1 100%; border-color: rgba(201, 184, 160, 0.35); color: var(--muted);
font-weight: 600; font-size: 0.82rem; gap: 0.5rem;
}
.wallet-fold {
margin: 0 0 1.15rem;
border: 1px solid rgba(232, 168, 56, 0.35);
border-radius: 14px;
overflow: hidden;
background: rgba(18, 28, 28, 0.55);
}
.wallet-fold-toggle {
display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
width: 100%; margin: 0; padding: 0.75rem 0.9rem; border: 0;
background: transparent; color: #f0d090; font: inherit; font-size: 0.95rem;
font-weight: 750; text-align: left; cursor: pointer;
}
.wallet-fold-toggle:hover { background: rgba(232, 168, 56, 0.1); }
.wallet-fold-toggle-text { flex: 1; }
.wallet-fold-chevron {
flex-shrink: 0; color: #3ecfbf; font-size: 1.1rem; font-weight: 700;
transition: transform 0.15s ease;
}
.wallet-fold.open .wallet-fold-chevron { transform: rotate(90deg); }
.wallet-fold-body {
display: none; padding: 0.15rem 0.9rem 1rem;
border-top: 1px solid rgba(232, 168, 56, 0.28);
}
.wallet-fold.open .wallet-fold-body { display: block; }
.wallet-fold-body .app-links { margin-top: 0.55rem; }
button.app-btn.cli-toggle {
flex: 1 1 100%; width: 100%; justify-content: flex-start; gap: 0.5rem;
font: inherit; font-weight: 700; font-size: 0.88rem; cursor: pointer;
color: #f0d090; border-color: rgba(232, 168, 56, 0.4); background: rgba(0,0,0,0.28);
}
button.app-btn.cli-toggle .cli-chevron {
margin-left: auto; flex-shrink: 0; color: #3ecfbf;
font-size: 1.15rem; font-weight: 700; line-height: 1;
transition: transform 0.15s ease;
}
button.app-btn.cli-toggle[aria-expanded="true"] .cli-chevron { transform: rotate(90deg); }
button.app-btn.cli-toggle[aria-expanded="true"] {
border-color: rgba(62, 207, 191, 0.5); background: rgba(62, 207, 191, 0.08);
}
.cli-panel {
display: none; width: 100%; margin: 0.35rem 0 0.55rem; text-align: left;
border: 1px solid rgba(232, 168, 56, 0.32); border-radius: 12px;
background: rgba(0, 0, 0, 0.28); padding: 0.75rem 0.85rem 0.9rem; box-sizing: border-box;
}
.cli-panel.open { display: block; }
.cli-panel .cli-lead {
margin: 0 0 0.55rem; color: var(--muted); font-size: 0.84rem; line-height: 1.4;
}
.cli-panel .cli-lead a { color: #e8c878; }
.cli-block {
margin: 0; padding: 0.55rem 0.65rem; border-radius: 10px;
background: rgba(0, 0, 0, 0.4); border: 1px solid rgba(240, 200, 106, 0.2);
color: #e8e0d0; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 0.7rem; line-height: 1.45; overflow-x: auto; white-space: pre; user-select: all;
}
.cli-block .cmt { color: #8a9a90; }
.sym-gold path, .sym-gold circle { fill: #f0c86a; stroke: #f0c86a; }
.sym-gold path[data-ring], .sym-gold circle[data-ring] { fill: none; stroke: #f0c86a; }
.sym-blue path, .sym-blue circle { fill: #3ecfbf; stroke: #3ecfbf; }
.sym-blue path[data-ring], .sym-blue circle[data-ring] { fill: none; stroke: #3ecfbf; }
.app-ico { width: 1.15rem; height: 1.15rem; flex-shrink: 0; display: block; }
.app-ico:not(.browser-ico) path,
.app-ico:not(.browser-ico) circle,
.app-ico:not(.browser-ico) rect { fill: currentColor; }
/* hub browser marks use explicit gold/blue fills in SVG */
.app-ico.stroke-ico path, .app-ico.stroke-ico circle, .app-ico.stroke-ico rect {
fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.app-ico.branch-ico circle { fill: currentColor; stroke: none; }
.app-ico.branch-ico path {
fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.app-btn:not(.hub) .app-ico { color: #f0c86a; }
.app-btn.ios .app-ico { color: #f0c86a; }
.hub-icons { display: inline-flex; align-items: center; gap: 0.4rem; }
.hub-icons .app-ico { width: 1.25rem; height: 1.25rem; }
.hub-icons .browser-ico { border-radius: 3px; flex-shrink: 0; }
.step-tagline .app-ico {
width: 1rem; height: 1rem; display: inline-block; vertical-align: -0.15em; margin: 0 0.12em;
}
.step-tagline .app-ico.android { color: #f0c86a; }
.step-tagline .app-ico.ios { color: #f0c86a; }
.step-body ol { margin: 0; padding-left: 1.2rem; width: 100%; align-self: stretch; color: var(--muted); }
.step-body li { margin: 0.35rem 0; }
footer { margin-top: 1.75rem; text-align: center; color: var(--muted); font-size: 0.85rem; }
footer a { color: #e8c878; }
code { font-family: ui-monospace, Menlo, monospace; font-size: 0.86em; background: rgba(0,0,0,0.35); padding: 0.1em 0.35em; border-radius: 4px; color: #f0d090; }
</style>
<script src="/intro/qrcode.min.js"></script>
</head>
<body>
<main>
<header class="hero">
<span class="badge">GOA · Exchange</span>
<h1>GOA Exchange</h1>
<p class="sub">Explorational exchange — coins, denoms, one-step withdraw.</p>
</header>
<section class="stats" id="stats-coins" aria-labelledby="coins-title">
<h2 id="coins-title">Coins</h2>
<p class="note">From exchange DB · coin lifecycle</p>
<div class="stats-grid">
<div class="stat"><span class="k">Known coins</span><span class="v teal" id="st-coins"></span></div>
<div class="stat"><span class="k">Live (remaining)</span><span class="v" id="st-coins-live"></span></div>
<div class="stat"><span class="k">Spent / zero</span><span class="v" id="st-coins-spent"></span></div>
<div class="stat"><span class="k">Remaining amt</span><span class="v teal sm" id="st-remaining"></span></div>
<div class="stat"><span class="k">Withdraw ops</span><span class="v" id="st-withdraw"></span></div>
<div class="stat"><span class="k">Withdraw amt</span><span class="v teal sm" id="st-withdraw-amt"></span></div>
<div class="stat"><span class="k">Refresh</span><span class="v" id="st-refresh"></span></div>
<div class="stat"><span class="k">Coin deposits</span><span class="v" id="st-coin-dep"></span></div>
<div class="stat"><span class="k">Batch deposits</span><span class="v" id="st-batch-dep"></span></div>
<div class="stat"><span class="k">Recoup</span><span class="v" id="st-recoup"></span></div>
<div class="stat"><span class="k">Refunds</span><span class="v" id="st-refunds"></span></div>
<div class="stat"><span class="k">History events</span><span class="v" id="st-hist"></span></div>
</div>
<div class="sub-block" id="by-denom-wrap" hidden>
<h3>Known coins by value</h3>
<div class="by-denom" id="st-by-denom"></div>
</div>
</section>
<section class="stats" id="stats-denoms" aria-labelledby="denoms-title">
<h2 id="denoms-title">Denominations</h2>
<p class="note">Signed keys in DB · public ladder on <code>/keys</code></p>
<div class="stats-grid">
<div class="stat"><span class="k">Denom keys</span><span class="v teal" id="st-denoms"></span></div>
<div class="stat"><span class="k">Unique values</span><span class="v" id="st-denom-vals"></span></div>
<div class="stat"><span class="k">Withdrawable now</span><span class="v teal" id="st-denoms-wd"></span></div>
</div>
<div class="sub-block">
<h3>Value ladder</h3>
<div class="ladder" id="st-ladder"></div>
</div>
</section>
<section class="stats" id="stats-wire" aria-labelledby="wire-title">
<h2 id="wire-title">Reserves · wire</h2>
<p class="note">Backing money movement</p>
<div class="stats-grid">
<div class="stat"><span class="k">Reserves</span><span class="v teal" id="st-reserves"></span></div>
<div class="stat"><span class="k">Wire in</span><span class="v" id="st-wire-in-n"></span></div>
<div class="stat"><span class="k">Wire in amt</span><span class="v teal sm" id="st-wire-in-amt"></span></div>
<div class="stat"><span class="k">Wire out</span><span class="v" id="st-wire-out"></span></div>
</div>
<p class="stats-foot" id="st-foot">Loading…</p>
<p class="stats-run-note" id="st-run-note" hidden></p>
</section>
<section class="stats" id="stats-perf" aria-labelledby="perf-title">
<h2 id="perf-title">Performance</h2>
<p class="note">Live HTTP probes + container memory (RSS)</p>
<div class="stats-grid">
<div class="stat"><span class="k">/keys</span><span class="v teal" id="st-keys-ms"></span></div>
<div class="stat"><span class="k">/config</span><span class="v" id="st-config-ms"></span></div>
<div class="stat"><span class="k">Loadavg</span><span class="v sm" id="st-load"></span></div>
<div class="stat"><span class="k">Container</span><span class="v teal" id="st-mem-ctr"></span></div>
<div class="stat"><span class="k">PostgreSQL</span><span class="v" id="st-mem-pg"></span></div>
<div class="stat"><span class="k">Taler procs</span><span class="v" id="st-mem-taler"></span></div>
<div class="stat"><span class="k">Nginx</span><span class="v sm" id="st-mem-nginx"></span></div>
</div>
<div class="sub-block" style="margin-top:0.85rem">
<h3>Top processes (RSS)</h3>
<div id="st-mem-top" class="by-denom"></div>
</div>
<p class="stats-foot" id="st-perf-foot">Memory from /proc + cgroup inside podman container.</p>
</section>
<div class="wallet-fold" id="wallet-fold">
<button type="button" class="wallet-fold-toggle" id="wallet-fold-toggle"
aria-expanded="false" aria-controls="wallet-fold-body">
<span class="wallet-fold-toggle-text">Get the wallet · Android / iOS / web / packages</span>
<span class="wallet-fold-chevron" aria-hidden="true"></span>
</button>
<div class="wallet-fold-body" id="wallet-fold-body" hidden>
<div class="app-links">
<a class="app-btn" href="https://play.google.com/store/apps/details?id=net.taler.wallet" target="_blank" rel="noopener noreferrer" aria-label="Android Play Store">
<svg class="app-ico" viewBox="0 0 24 24" aria-hidden="true"><path d="M8.2 2.4l-.9-1.6c-.1-.2 0-.4.2-.5.2-.1.4 0 .5.2l.9 1.6c.8-.3 1.7-.5 2.6-.5s1.8.2 2.6.5l.9-1.6c.1-.2.3-.3.5-.2.2.1.3.3.2.5l-.9 1.6c1.8.8 3.1 2.5 3.3 4.6H4.9c.2-2.1 1.5-3.8 3.3-4.6zM7 8.5c.6 0 1 .4 1 1s-.4 1-1 1-1-.4-1-1 .4-1 1-1zm10 0c.6 0 1 .4 1 1s-.4 1-1 1-1-.4-1-1 .4-1 1-1zM5 10.5h14c.6 0 1 .4 1 1v6.2c0 1.3-1 2.3-2.3 2.3h-.5v2.2c0 .5-.4.9-.9.9s-.9-.4-.9-.9v-2.2h-4.8v2.2c0 .5-.4.9-.9.9s-.9-.4-.9-.9v-2.2h-.5C5.9 20 5 19 5 17.7v-6.2c0-.6.4-1 1-1z"/></svg>
Play Store
</a>
<a class="app-btn" href="https://f-droid.org/en/packages/net.taler.wallet.fdroid/" target="_blank" rel="noopener noreferrer" aria-label="Android F-Droid">
<svg class="app-ico" viewBox="0 0 24 24" aria-hidden="true"><path d="M8.2 2.4l-.9-1.6c-.1-.2 0-.4.2-.5.2-.1.4 0 .5.2l.9 1.6c.8-.3 1.7-.5 2.6-.5s1.8.2 2.6.5l.9-1.6c.1-.2.3-.3.5-.2.2.1.3.3.2.5l-.9 1.6c1.8.8 3.1 2.5 3.3 4.6H4.9c.2-2.1 1.5-3.8 3.3-4.6zM7 8.5c.6 0 1 .4 1 1s-.4 1-1 1-1-.4-1-1 .4-1 1-1zm10 0c.6 0 1 .4 1 1s-.4 1-1 1-1-.4-1-1 .4-1 1-1zM5 10.5h14c.6 0 1 .4 1 1v6.2c0 1.3-1 2.3-2.3 2.3h-.5v2.2c0 .5-.4.9-.9.9s-.9-.4-.9-.9v-2.2h-4.8v2.2c0 .5-.4.9-.9.9s-.9-.4-.9-.9v-2.2h-.5C5.9 20 5 19 5 17.7v-6.2c0-.6.4-1 1-1z"/></svg>
F-Droid
</a>
<a class="app-btn ios" href="https://apps.apple.com/app/taler-wallet/id6463440117" target="_blank" rel="noopener noreferrer" aria-label="iOS App Store">
<svg class="app-ico" viewBox="0 0 24 24" aria-hidden="true"><path d="M16.7 12.6c0-2.1 1.7-3.1 1.8-3.2-1-1.4-2.5-1.6-3-1.7-1.3-.1-2.5.8-3.1.8s-1.6-.7-2.7-.7c-1.4 0-2.7.8-3.4 2.1-1.5 2.5-.4 6.3 1 8.3.7 1 1.5 2.1 2.6 2 1-.1 1.5-.7 2.8-.7s1.7.7 2.8.7 1.9-1 2.6-2c.8-1.1 1.1-2.2 1.1-2.3-.1 0-2.2-.8-2.2-3.3zm-2-6.2c.6-.7 1-1.7.9-2.7-1 .1-2.1.6-2.8 1.4-.6.7-1.1 1.7-.9 2.6 1 .1 2-.5 2.8-1.3z"/></svg>
App Store
</a>
<a class="app-btn hub" href="https://wallet.taler.net/" target="_blank" rel="noopener noreferrer" aria-label="Web browsers (experimental): Chrome, Firefox, Opera, Ubuntu Touch">
<span class="hub-icons" aria-hidden="true" title="Chrome · Firefox · Opera · Ubuntu Touch">
<svg class="app-ico browser-ico" viewBox="0 0 24 24" role="img" aria-label="Chrome">
<circle cx="12" cy="12" r="10" fill="#3ecfbf" opacity="0.22"/>
<path fill="#3ecfbf" d="M12 2a10 10 0 0 1 8.66 5H12a4 4 0 0 0-3.46 2L5.1 4.1A10 10 0 0 1 12 2z"/>
<path fill="#3ecfbf" opacity="0.8" d="M20.66 7A10 10 0 0 1 12 22l3.46-6A4 4 0 0 0 12 8h8.66z"/>
<path fill="#3ecfbf" opacity="0.55" d="M5.1 4.1 8.54 9A4 4 0 0 0 12 16l-3.46 6A10 10 0 0 1 5.1 4.1z"/>
<circle cx="12" cy="12" r="3.2" fill="#3ecfbf"/>
</svg>
<svg class="app-ico browser-ico" viewBox="0 0 24 24" role="img" aria-label="Firefox">
<circle cx="12" cy="12.2" r="8.2" fill="#3ecfbf" opacity="0.28"/>
<path fill="#3ecfbf" d="M20.2 9.2c-.2-1.4-1.1-2.6-2.2-3.4.5 1.1.6 2.3.3 3.4-.9-1.6-2.5-2.6-4.4-2.6-1.3 0-2.5.4-3.4 1.1C9.3 5.4 10.9 3.8 13 3.2c-2.5.1-4.7 1.4-6.1 3.4C5.3 8.2 4.6 10.2 4.8 12.3c.3 3.9 3.5 7 7.4 7.1 3.6.1 6.7-2.2 7.7-5.5.4-1.4.4-2.9.3-4.7z"/>
<circle cx="12.2" cy="13.2" r="2.4" fill="#3ecfbf"/>
</svg>
<svg class="app-ico browser-ico" viewBox="0 0 24 24" role="img" aria-label="Opera">
<circle cx="12" cy="12" r="9.2" fill="none" stroke="#3ecfbf" stroke-width="2"/>
<ellipse cx="12" cy="12" rx="4.15" ry="7.1" fill="none" stroke="#3ecfbf" stroke-width="1.85"/>
</svg>
<svg class="app-ico browser-ico" viewBox="0 0 24 24" role="img" aria-label="Ubuntu Touch">
<circle cx="12" cy="12" r="2.25" fill="#3ecfbf"/>
<circle cx="12" cy="4.85" r="1.7" fill="#3ecfbf"/>
<circle cx="18.15" cy="15.55" r="1.7" fill="#3ecfbf"/>
<circle cx="5.85" cy="15.55" r="1.7" fill="#3ecfbf"/>
</svg>
</span>
Web browsers (experimental)
</a>
<button type="button" class="app-btn hub cli-toggle" id="pkg-fold-toggle"
aria-expanded="false" aria-controls="pkg-fold-body"
aria-label="Linux packages: Debian and Ubuntu (taler-wallet-cli)">
<svg class="app-ico browser-ico penguin-ico" viewBox="0 0 24 24" role="img" aria-label="Linux">
<ellipse cx="12" cy="14.2" rx="6.4" ry="7.2" fill="#f0c86a"/>
<ellipse cx="12" cy="15.2" rx="3.6" ry="4.8" fill="#1a1410" opacity="0.35"/>
<circle cx="12" cy="7" r="4.1" fill="#f0c86a"/>
<circle cx="10.35" cy="6.6" r="0.85" fill="#1a1410"/>
<circle cx="13.65" cy="6.6" r="0.85" fill="#1a1410"/>
<path fill="#e8a838" d="M11.15 8.1 12 9.55 12.85 8.1z"/>
<ellipse cx="9.4" cy="21" rx="2.1" ry="1.05" fill="#e8a838"/>
<ellipse cx="14.6" cy="21" rx="2.1" ry="1.05" fill="#e8a838"/>
<ellipse cx="6.6" cy="13.5" rx="1.4" ry="2.6" fill="#f0c86a" transform="rotate(-18 6.6 13.5)"/>
<ellipse cx="17.4" cy="13.5" rx="1.4" ry="2.6" fill="#f0c86a" transform="rotate(18 17.4 13.5)"/>
</svg>
Debian · Ubuntu packages
<span class="cli-chevron" aria-hidden="true"></span>
</button>
<div class="cli-panel" id="pkg-fold-body" hidden>
<p class="cli-lead">
Official <strong>taler-wallet-cli</strong> from
<a href="https://deb.taler.net/" target="_blank" rel="noopener noreferrer">deb.taler.net</a>.
More on the <a href="https://bank.hacktivism.ch/intro/">bank landing</a>.
</p>
<pre class="cli-block"><span class="cmt"># Debian example</span>
sudo apt-get update
sudo apt-get install -y taler-wallet-cli</pre>
</div>
</div>
</div>
</div>
<section class="step-card">
<h2>Withdraw GOA</h2>
<p class="step-tagline">One-step: add exchange + withdraw</p>
<div class="step-body">
<div class="qr-box">
<div id="qr-exchange"></div>
<div class="qr-label">Scan in wallet</div>
</div>
<a class="cta teal" href="taler://withdraw-exchange/exchange.hacktivism.ch/">Open in wallet →</a>
<p class="meta">taler://withdraw-exchange/exchange.hacktivism.ch/</p>
<div class="links">
<a class="cta-sec" href="https://bank.hacktivism.ch/intro/">Bank →</a>
<a class="cta-sec" href="https://exchange.hacktivism.ch/keys">/keys</a>
<a class="cta-sec" href="https://exchange.hacktivism.ch/terms">/terms</a>
<a class="cta-sec" href="https://exchange.hacktivism.ch/privacy">/privacy</a>
<a class="cta-sec" href="https://exchange.hacktivism.ch/config">/config</a>
</div>
</div>
</section>
<footer>
<a href="https://bank.hacktivism.ch/intro/">Bank</a> ·
<a href="https://exchange.hacktivism.ch/intro/">Exchange</a> ·
<a href="https://taler.hacktivism.ch/intro/">Merchant</a> ·
<a href="https://exchange.hacktivism.ch/terms">Terms</a> ·
<a href="https://exchange.hacktivism.ch/privacy">Privacy</a> ·
<a href="https://git.hacktivism.ch/hernani/koopa-admin-log/src/branch/main/configs/exchange-landing">Source</a>
<p class="privacy-note" style="margin:0.65rem 0 0;font-size:0.78rem;color:var(--muted);line-height:1.4">
Privacy: processing under Swiss FADP (revDSG). What is retained is listed on
<a href="https://exchange.hacktivism.ch/privacy" style="color:#5eead4">/privacy</a>.
</p>
</footer>
</main>
<script>
(function () {
function set(id, v) {
var el = document.getElementById(id);
if (el) el.textContent = v == null || v === "" ? "—" : String(v);
}
function msLabel(ms, http) {
if (ms == null || ms === "") return "—";
var s = ms + " ms";
if (http && http !== "200") s += " (" + http + ")";
return s;
}
fetch("/intro/stats.json", { cache: "no-store" })
.then(function (r) { if (!r.ok) throw new Error("x"); return r.json(); })
.then(function (d) {
if (!d || !d.ok) throw new Error("bad");
set("st-coins", d.known_coins);
set("st-coins-live", d.coins_live);
set("st-coins-spent", d.coins_spent);
set("st-remaining", d.coins_remaining_amount);
set("st-withdraw", d.withdraw_ops);
set("st-withdraw-amt", d.withdraw_amount);
set("st-refresh", d.refresh_ops);
set("st-coin-dep", d.coin_deposits);
set("st-batch-dep", d.batch_deposits);
set("st-recoup", d.recoup);
set("st-refunds", d.refunds);
set("st-hist", d.coin_history_events);
set("st-denoms", d.denominations);
set("st-denom-vals", d.denom_values);
set("st-denoms-wd", d.denoms_withdrawable);
set("st-reserves", d.reserves);
set("st-wire-in-n", d.wire_in_count);
set("st-wire-in-amt", d.wire_in_amount);
set("st-wire-out", d.wire_out);
var ladder = document.getElementById("st-ladder");
if (ladder) {
ladder.innerHTML = "";
(d.denom_ladder || []).forEach(function (x) {
var s = document.createElement("span");
s.className = "pill";
s.textContent = x.value + (x.keys > 1 ? " ×" + x.keys : "");
ladder.appendChild(s);
});
if (!(d.denom_ladder || []).length) ladder.textContent = "—";
}
var by = d.by_denom || [];
var wrap = document.getElementById("by-denom-wrap");
var box = document.getElementById("st-by-denom");
if (wrap && box && by.length) {
wrap.hidden = false;
var html = "<table><thead><tr><th>Value</th><th>Coins</th><th>Live</th></tr></thead><tbody>";
by.forEach(function (r) {
html += "<tr><td>" + r.value + "</td><td>" + r.coins + "</td><td>" + r.live + "</td></tr>";
});
html += "</tbody></table>";
box.innerHTML = html;
}
var foot = document.getElementById("st-foot");
if (foot) {
foot.textContent = (d.wirewatch_running ? "wirewatch on · " : "wirewatch off · ") +
(d.generated_at_human || d.generated_at || "");
}
var p = d.performance || {};
set("st-keys-ms", msLabel(p.keys_ms, p.keys_http));
set("st-config-ms", msLabel(p.config_ms, p.config_http));
set("st-load", p.loadavg || "—");
var mem = p.memory || {};
set("st-mem-ctr", mem.container_rss_human || "—");
set("st-mem-pg", mem.postgres_rss_human
? mem.postgres_rss_human + (mem.postgres_n ? " · " + mem.postgres_n + "p" : "")
: "—");
set("st-mem-taler", mem.taler_rss_human
? mem.taler_rss_human + (mem.taler_n ? " · " + mem.taler_n + "p" : "")
: "—");
set("st-mem-nginx", mem.nginx_rss_human || "—");
var topBox = document.getElementById("st-mem-top");
if (topBox) {
var tops = mem.top || [];
if (!tops.length) {
topBox.textContent = "—";
} else {
var th = "<table><thead><tr><th>RSS</th><th>Comm</th><th>Command</th></tr></thead><tbody>";
tops.forEach(function (t) {
th += "<tr><td>" + (t.rss_human || "?") + "</td><td>" +
(t.comm || "") + "</td><td style=\"font-size:0.72rem;word-break:break-all\">" +
(t.cmd || "") + "</td></tr>";
});
th += "</tbody></table>";
topBox.innerHTML = th;
}
}
var pf = document.getElementById("st-perf-foot");
if (pf) {
pf.textContent = "Container RSS + process groups · " +
(d.generated_at_human || d.generated_at || "");
}
return fetch("/intro/stats-run.json", { cache: "no-store" })
.then(function (r) { return r.ok ? r.json() : null; })
.catch(function () { return null; });
})
.then(function (run) {
var note = document.getElementById("st-run-note");
if (!note) return;
if (run && run.ok === false) {
note.hidden = false;
note.textContent = "Last refresh failed" +
(run.at_human ? " · " + run.at_human : "") +
" · showing last good data";
} else {
note.hidden = true;
note.textContent = "";
}
})
.catch(function () {
var foot = document.getElementById("st-foot");
if (foot) foot.innerHTML = 'Stats offline · <a href="https://bank.hacktivism.ch/intro/" style="color:#e8c878">bank.hacktivism.ch</a>';
});
var el = document.getElementById("qr-exchange");
if (el && typeof QRCode !== "undefined") {
new QRCode(el, {
text: "taler://withdraw-exchange/exchange.hacktivism.ch/",
width: 220, height: 220, correctLevel: QRCode.CorrectLevel.M
});
}
})();
</script>
<script>
(function () {
var fold = document.getElementById("wallet-fold");
var btn = document.getElementById("wallet-fold-toggle");
var body = document.getElementById("wallet-fold-body");
if (fold && btn && body) {
btn.addEventListener("click", function () {
var open = !fold.classList.contains("open");
fold.classList.toggle("open", open);
btn.setAttribute("aria-expanded", open ? "true" : "false");
if (open) body.removeAttribute("hidden");
else body.setAttribute("hidden", "");
});
}
function wireCli(btnId, bodyId) {
var b = document.getElementById(btnId);
var p = document.getElementById(bodyId);
if (!b || !p) return;
b.addEventListener("click", function () {
var open = !p.classList.contains("open");
p.classList.toggle("open", open);
b.setAttribute("aria-expanded", open ? "true" : "false");
if (open) p.removeAttribute("hidden");
else p.setAttribute("hidden", "");
});
}
wireCli("pkg-fold-toggle", "pkg-fold-body");
})();
</script>
</body>
</html>