bank landing: community-shared explorer withdraw UI and how-it-works
This commit is contained in:
parent
57973db4f0
commit
31c8dcdb9c
1 changed files with 161 additions and 16 deletions
|
|
@ -82,6 +82,32 @@
|
||||||
border: 1px solid rgba(232, 168, 56, 0.4);
|
border: 1px solid rgba(232, 168, 56, 0.4);
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
}
|
}
|
||||||
|
.community-note,
|
||||||
|
.how-note {
|
||||||
|
margin: 0 0 1.15rem;
|
||||||
|
padding: 0.8rem 0.95rem;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
line-height: 1.45;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.community-note {
|
||||||
|
background: rgba(94, 234, 212, 0.1);
|
||||||
|
border: 1px solid rgba(94, 234, 212, 0.4);
|
||||||
|
color: #ccfbf1;
|
||||||
|
}
|
||||||
|
.community-note strong { color: #5eead4; font-weight: 750; }
|
||||||
|
.how-note {
|
||||||
|
background: rgba(232, 168, 56, 0.08);
|
||||||
|
border: 1px solid rgba(232, 168, 56, 0.35);
|
||||||
|
color: #f5e6c8;
|
||||||
|
}
|
||||||
|
.how-note strong { color: #f0c86a; font-weight: 750; }
|
||||||
|
.how-note ol {
|
||||||
|
margin: 0.4rem 0 0;
|
||||||
|
padding-left: 1.2rem;
|
||||||
|
}
|
||||||
|
.how-note li { margin: 0.25rem 0; }
|
||||||
|
|
||||||
.step-card {
|
.step-card {
|
||||||
background: var(--card);
|
background: var(--card);
|
||||||
|
|
@ -535,10 +561,17 @@
|
||||||
<span class="badge">Exploration · GOA</span>
|
<span class="badge">Exploration · GOA</span>
|
||||||
<h1>GOA Exploration Bank</h1>
|
<h1>GOA Exploration Bank</h1>
|
||||||
<p class="sub">
|
<p class="sub">
|
||||||
Install the wallet, then <strong>one QR</strong> adds the exchange and starts a withdraw.
|
Install the wallet, then <strong>one QR</strong> withdraws GOA from a
|
||||||
|
<strong>community-shared bank account</strong> — no personal bank registration.
|
||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<p class="community-note" role="note">
|
||||||
|
<strong>Community pool.</strong>
|
||||||
|
Demo GOA comes from one shared exploration account used by everyone on this site
|
||||||
|
(not your private bank login). Balance is shared; amounts are small; for play only.
|
||||||
|
</p>
|
||||||
|
|
||||||
<!-- ========== LIVE STATS ========== -->
|
<!-- ========== LIVE STATS ========== -->
|
||||||
<section class="stats" id="stats" aria-labelledby="stats-title" hidden>
|
<section class="stats" id="stats" aria-labelledby="stats-title" hidden>
|
||||||
<h2 id="stats-title">GOA flow</h2>
|
<h2 id="stats-title">GOA flow</h2>
|
||||||
|
|
@ -683,23 +716,36 @@
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ========== STEP 2: one-step withdraw-exchange ========== -->
|
<!-- ========== STEP 2: one-click community pool withdraw ========== -->
|
||||||
<section class="step-card step-money" aria-labelledby="step2-title">
|
<section class="step-card step-money" id="withdraw" aria-labelledby="step2-title">
|
||||||
<h2 id="step2-title"><span class="step-num">2</span> Withdraw GOA</h2>
|
<h2 id="step2-title"><span class="step-num">2</span> Withdraw GOA</h2>
|
||||||
<p class="step-tagline">One-step: add exchange + withdraw</p>
|
<p class="step-tagline">One QR · community-shared account · no registration</p>
|
||||||
<div class="step-body">
|
<div class="step-body">
|
||||||
<div class="qr-box">
|
<div class="qr-box">
|
||||||
<div id="qr-withdraw-exchange"></div>
|
<div id="qr-withdraw-demo"></div>
|
||||||
<div class="qr-label">Scan or open in wallet</div>
|
<div class="qr-label">Scan or open in wallet</div>
|
||||||
</div>
|
</div>
|
||||||
<a class="cta teal" id="open-withdraw-exchange"
|
<a class="cta teal" id="open-withdraw-demo" href="#">
|
||||||
href="taler://withdraw-exchange/exchange.hacktivism.ch/">
|
|
||||||
Open in wallet →
|
Open in wallet →
|
||||||
</a>
|
</a>
|
||||||
<p class="meta">taler://withdraw-exchange/exchange.hacktivism.ch/</p>
|
<p class="meta" id="withdraw-demo-meta">Preparing community withdraw…</p>
|
||||||
|
<p class="meta" id="withdraw-demo-amount" hidden></p>
|
||||||
|
<button type="button" class="cta-sec" id="withdraw-demo-refresh" style="margin-top:0.5rem">
|
||||||
|
Get a fresh QR
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<aside class="how-note" aria-labelledby="how-title">
|
||||||
|
<strong id="how-title">How this works</strong>
|
||||||
|
<ol>
|
||||||
|
<li>A <strong>community-shared bank account</strong> (demo pool) already holds GOA.</li>
|
||||||
|
<li>Each “Open in wallet” / QR creates a <strong>one-shot withdraw</strong> from that pool — you do <em>not</em> open your own bank account.</li>
|
||||||
|
<li>Your GNU Taler app receives coins after the bank confirms (automatic on this demo).</li>
|
||||||
|
<li>Optional below: register your <em>own</em> bank UI account if you want a private balance.</li>
|
||||||
|
</ol>
|
||||||
|
</aside>
|
||||||
|
|
||||||
<!-- ========== Optional bank UI + mini GOA shop teaser ========== -->
|
<!-- ========== Optional bank UI + mini GOA shop teaser ========== -->
|
||||||
<div class="more-section">
|
<div class="more-section">
|
||||||
<span class="more-label">Optional · bank UI & GOA shop</span>
|
<span class="more-label">Optional · bank UI & GOA shop</span>
|
||||||
|
|
@ -757,25 +803,124 @@
|
||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
var WEBUI = "https://bank.hacktivism.ch/webui/";
|
var WEBUI = "https://bank.hacktivism.ch/webui/";
|
||||||
/* taler-ops one-step: add exchange + start withdraw */
|
/* Secondary: own-account path (register first) */
|
||||||
var WITHDRAW_EXCHANGE = "taler://withdraw-exchange/exchange.hacktivism.ch/";
|
var WITHDRAW_EXCHANGE = "taler://withdraw-exchange/exchange.hacktivism.ch/";
|
||||||
|
|
||||||
function makeQr(el, text) {
|
function makeQr(el, text) {
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
el.innerHTML = "";
|
el.innerHTML = "";
|
||||||
|
if (!text) {
|
||||||
|
el.textContent = "…";
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (typeof QRCode === "undefined") {
|
if (typeof QRCode === "undefined") {
|
||||||
el.textContent = "QR lib missing";
|
el.textContent = "QR lib missing";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
new QRCode(el, {
|
// Encode off-DOM so QR is visible (canvas/img not collapsed)
|
||||||
text: text,
|
var size = 220;
|
||||||
width: 220,
|
var scratch = document.createElement("div");
|
||||||
height: 220,
|
scratch.style.cssText =
|
||||||
correctLevel: QRCode.CorrectLevel.M
|
"position:fixed;left:-9999px;top:0;width:" + size + "px;height:" + size + "px;opacity:0";
|
||||||
});
|
document.body.appendChild(scratch);
|
||||||
|
try {
|
||||||
|
new QRCode(scratch, {
|
||||||
|
text: String(text),
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
colorDark: "#000000",
|
||||||
|
colorLight: "#ffffff",
|
||||||
|
correctLevel: QRCode.CorrectLevel.M
|
||||||
|
});
|
||||||
|
var canvas = scratch.querySelector("canvas");
|
||||||
|
var dataUrl = canvas ? canvas.toDataURL("image/png") : "";
|
||||||
|
if (dataUrl) {
|
||||||
|
var img = document.createElement("img");
|
||||||
|
img.alt = "QR code";
|
||||||
|
img.width = size;
|
||||||
|
img.height = size;
|
||||||
|
img.src = dataUrl;
|
||||||
|
img.style.display = "block";
|
||||||
|
img.style.margin = "0 auto";
|
||||||
|
el.appendChild(img);
|
||||||
|
} else {
|
||||||
|
el.appendChild(scratch.firstChild || document.createTextNode("QR failed"));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
el.textContent = "QR encode failed";
|
||||||
|
}
|
||||||
|
if (scratch.parentNode) scratch.parentNode.removeChild(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
makeQr(document.getElementById("qr-withdraw-exchange"), WITHDRAW_EXCHANGE);
|
function setDemoWithdraw(uri, amount) {
|
||||||
|
uri = String(uri || "").replace(/:443\//g, "/").replace(/:443\?/g, "?");
|
||||||
|
var open = document.getElementById("open-withdraw-demo");
|
||||||
|
var meta = document.getElementById("withdraw-demo-meta");
|
||||||
|
var amtEl = document.getElementById("withdraw-demo-amount");
|
||||||
|
if (open) {
|
||||||
|
open.href = uri;
|
||||||
|
open.classList.remove("disabled");
|
||||||
|
}
|
||||||
|
if (meta) meta.textContent = uri;
|
||||||
|
if (amtEl) {
|
||||||
|
if (amount) {
|
||||||
|
amtEl.hidden = false;
|
||||||
|
amtEl.textContent = "Amount: " + amount + " · from community pool";
|
||||||
|
} else {
|
||||||
|
amtEl.hidden = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
makeQr(document.getElementById("qr-withdraw-demo"), uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadDemoWithdraw() {
|
||||||
|
var meta = document.getElementById("withdraw-demo-meta");
|
||||||
|
var open = document.getElementById("open-withdraw-demo");
|
||||||
|
if (meta) meta.textContent = "Preparing community withdraw…";
|
||||||
|
if (open) {
|
||||||
|
open.removeAttribute("href");
|
||||||
|
open.classList.add("disabled");
|
||||||
|
}
|
||||||
|
// Prefer live mint (fresh op each time); fall back to static withdraw.uri
|
||||||
|
fetch("/intro/demo-withdraw.json", { cache: "no-store" })
|
||||||
|
.then(function (r) {
|
||||||
|
if (!r.ok) throw new Error("HTTP " + r.status);
|
||||||
|
return r.json();
|
||||||
|
})
|
||||||
|
.then(function (d) {
|
||||||
|
if (!d || !d.taler_withdraw_uri) throw new Error(d && d.error ? d.error : "no uri");
|
||||||
|
setDemoWithdraw(d.taler_withdraw_uri, d.amount || "");
|
||||||
|
})
|
||||||
|
.catch(function () {
|
||||||
|
return fetch("/intro/withdraw.uri", { cache: "no-store" })
|
||||||
|
.then(function (r) {
|
||||||
|
if (!r.ok) throw new Error("no fallback");
|
||||||
|
return r.text();
|
||||||
|
})
|
||||||
|
.then(function (t) {
|
||||||
|
var uri = String(t || "").trim();
|
||||||
|
if (!uri) throw new Error("empty");
|
||||||
|
return fetch("/intro/withdraw.amount", { cache: "no-store" })
|
||||||
|
.then(function (r) {
|
||||||
|
return r.ok ? r.text() : Promise.resolve("");
|
||||||
|
})
|
||||||
|
.then(function (a) {
|
||||||
|
setDemoWithdraw(uri, String(a || "").trim());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
if (meta) {
|
||||||
|
meta.textContent =
|
||||||
|
"Could not prepare withdraw — try again or use bank UI. " +
|
||||||
|
(err && err.message ? err.message : "");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadDemoWithdraw();
|
||||||
|
var refreshBtn = document.getElementById("withdraw-demo-refresh");
|
||||||
|
if (refreshBtn) refreshBtn.onclick = function () { loadDemoWithdraw(); };
|
||||||
makeQr(document.getElementById("qr-webui"), WEBUI);
|
makeQr(document.getElementById("qr-webui"), WEBUI);
|
||||||
|
|
||||||
function fmtCest(unix, fallback) {
|
function fmtCest(unix, fallback) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue