bank landing: one-step withdraw-exchange + Android/iOS links
Short intro; wallet install; single taler://withdraw-exchange QR.
This commit is contained in:
parent
8729e69e87
commit
5af039ca03
2 changed files with 96 additions and 145 deletions
|
|
@ -13,33 +13,25 @@ open your own bank account, and point merchants at `taler.hacktivism.ch`.
|
||||||
|
|
||||||
## User flow (documented on the page)
|
## User flow (documented on the page)
|
||||||
|
|
||||||
### Two steps (only path)
|
Same **one-step** pattern as [taler-ops.ch Android/iOS guides](https://taler-ops.ch/en/users-android.html):
|
||||||
|
|
||||||
1. **`taler://add-exchange/exchange.hacktivism.ch/`** — add exchange, accept ToS.
|
1. **Install wallet** — Android (Play Store / F-Droid) and iOS (App Store), plus hub `wallet.taler.net`.
|
||||||
2. **Demo withdraw URI** from `withdraw.uri` — bank-integrated withdraw (default `GOA:10`).
|
2. **One QR / link** — `taler://withdraw-exchange/exchange.hacktivism.ch/`
|
||||||
|
Adds the GOA exchange **and** starts withdrawal (accept ToS → enter amount).
|
||||||
|
|
||||||
If the demo withdraw is already **confirmed/aborted**, the page points at the bank UI instead.
|
The old two-step path (`taler://add-exchange/…` + demo `taler://withdraw/…` from `withdraw.uri`) is **removed** from the landing.
|
||||||
|
|
||||||
|
Optional: bank UI (`/webui/`) and merchant (`taler.hacktivism.ch`) stay further down.
|
||||||
|
|
||||||
### CLI sketch (fresh wallet DB)
|
### CLI sketch (fresh wallet DB)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# equivalent one-step in CLI terms:
|
||||||
taler-wallet-cli exchanges add https://exchange.hacktivism.ch/
|
taler-wallet-cli exchanges add https://exchange.hacktivism.ch/
|
||||||
taler-wallet-cli exchanges accept-tos https://exchange.hacktivism.ch/
|
taler-wallet-cli exchanges accept-tos https://exchange.hacktivism.ch/
|
||||||
taler-wallet-cli withdraw accept-uri --exchange https://exchange.hacktivism.ch/ 'taler://withdraw/…'
|
# then withdraw from the exchange (amount chosen in wallet UI)
|
||||||
# then bank confirm (demo often auto-confirms) + run-until-done
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### URI note (`:443`)
|
|
||||||
|
|
||||||
libeufin may emit:
|
|
||||||
|
|
||||||
```text
|
|
||||||
taler://withdraw/bank.hacktivism.ch:443/taler-integration/<uuid>
|
|
||||||
```
|
|
||||||
|
|
||||||
Explicit default HTTPS port. Valid for wallets; the landing page **strips `:443`** for
|
|
||||||
QR / open links when the host is the public bank name. Both forms work.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Live stats (in bank container)
|
## Live stats (in bank container)
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
.sub {
|
.sub {
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: 28rem;
|
max-width: 30rem;
|
||||||
font-size: 1.05rem;
|
font-size: 1.05rem;
|
||||||
line-height: 1.45;
|
line-height: 1.45;
|
||||||
}
|
}
|
||||||
|
|
@ -83,7 +83,6 @@
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Big step cards */
|
|
||||||
.step-card {
|
.step-card {
|
||||||
background: var(--card);
|
background: var(--card);
|
||||||
backdrop-filter: blur(12px);
|
backdrop-filter: blur(12px);
|
||||||
|
|
@ -168,7 +167,9 @@
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
color: #3a342c;
|
color: #3a342c;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
max-width: 220px;
|
max-width: 240px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
.cta {
|
.cta {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
@ -196,15 +197,6 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
#status {
|
|
||||||
min-height: 1.1em;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
color: var(--muted);
|
|
||||||
margin: 0.4rem 0 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
#status.err { color: #f0a090; }
|
|
||||||
#status.ok { color: var(--accent2); }
|
|
||||||
code {
|
code {
|
||||||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||||
font-size: 0.86em;
|
font-size: 0.86em;
|
||||||
|
|
@ -214,7 +206,42 @@
|
||||||
color: #f0d090;
|
color: #f0d090;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Distinct “more options” section further down */
|
/* App store buttons */
|
||||||
|
.app-links {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.55rem;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.app-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
min-width: 9.5rem;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 0.92rem;
|
||||||
|
padding: 0.65rem 0.95rem;
|
||||||
|
border-radius: 11px;
|
||||||
|
border: 1px solid rgba(232, 168, 56, 0.4);
|
||||||
|
background: rgba(0, 0, 0, 0.28);
|
||||||
|
color: #f0d090;
|
||||||
|
}
|
||||||
|
.app-btn:hover { filter: brightness(1.08); border-color: rgba(240, 200, 106, 0.7); }
|
||||||
|
.app-btn.ios {
|
||||||
|
border-color: rgba(62, 207, 191, 0.4);
|
||||||
|
color: #b8f5ec;
|
||||||
|
}
|
||||||
|
.app-btn.hub {
|
||||||
|
flex: 1 1 100%;
|
||||||
|
border-color: rgba(201, 184, 160, 0.35);
|
||||||
|
color: var(--muted);
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
.more-section {
|
.more-section {
|
||||||
margin-top: 2.75rem;
|
margin-top: 2.75rem;
|
||||||
padding-top: 1.75rem;
|
padding-top: 1.75rem;
|
||||||
|
|
@ -285,7 +312,6 @@
|
||||||
transform-origin: center top;
|
transform-origin: center top;
|
||||||
opacity: 0.95;
|
opacity: 0.95;
|
||||||
}
|
}
|
||||||
/* Live stats (written by in-container landing-stats.sh → stats.json) */
|
|
||||||
.stats {
|
.stats {
|
||||||
background: rgba(18, 28, 28, 0.55);
|
background: rgba(18, 28, 28, 0.55);
|
||||||
border: 1px solid rgba(62, 207, 191, 0.28);
|
border: 1px solid rgba(62, 207, 191, 0.28);
|
||||||
|
|
@ -335,7 +361,6 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.stat .v.teal { color: #5eead4; }
|
.stat .v.teal { color: #5eead4; }
|
||||||
.stat .v.muted { color: var(--muted); font-size: 0.92rem; font-weight: 600; }
|
|
||||||
.stat.wide { grid-column: 1 / -1; }
|
.stat.wide { grid-column: 1 / -1; }
|
||||||
.wd-list {
|
.wd-list {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
|
@ -391,14 +416,14 @@
|
||||||
<body>
|
<body>
|
||||||
<main>
|
<main>
|
||||||
<header class="hero">
|
<header class="hero">
|
||||||
<span class="badge">Intergalactic · GOA · no IBAN</span>
|
<span class="badge">Exploration · GOA</span>
|
||||||
<h1>GOA Exploration Bank</h1>
|
<h1>GOA Exploration Bank</h1>
|
||||||
<p class="sub">
|
<p class="sub">
|
||||||
Two steps to put <strong>GOA</strong> in your GNU Taler wallet.
|
Install the wallet, then <strong>one QR</strong> adds the exchange and starts a withdraw.
|
||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<!-- ========== LIVE STATS (stats.json from bank container) ========== -->
|
<!-- ========== 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>
|
||||||
<div class="stats-grid">
|
<div class="stats-grid">
|
||||||
|
|
@ -483,64 +508,62 @@
|
||||||
<p class="stats-foot" id="st-perf-foot">Memory from /proc + cgroup inside podman container.</p>
|
<p class="stats-foot" id="st-perf-foot">Memory from /proc + cgroup inside podman container.</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ========== STEP 1 ========== -->
|
<!-- ========== STEP 1: install apps ========== -->
|
||||||
<section class="step-card" aria-labelledby="step1-title">
|
<section class="step-card" aria-labelledby="step1-title">
|
||||||
<h2 id="step1-title"><span class="step-num">1</span> Add the exchange</h2>
|
<h2 id="step1-title"><span class="step-num">1</span> Get the wallet</h2>
|
||||||
<p class="step-tagline">Tell the wallet where GOA coins come from.</p>
|
<p class="step-tagline">Android or iOS</p>
|
||||||
<div class="step-body">
|
<div class="step-body">
|
||||||
<ol>
|
<div class="app-links">
|
||||||
<li>Install the <strong>GNU Taler Wallet</strong> (phone app or browser extension).</li>
|
<a class="app-btn"
|
||||||
<li>Scan the QR with the wallet, or tap the button.</li>
|
href="https://play.google.com/store/apps/details?id=net.taler.wallet"
|
||||||
<li>Confirm / trust <code>exchange.hacktivism.ch</code>.</li>
|
target="_blank" rel="noopener noreferrer">
|
||||||
</ol>
|
Android · Play Store
|
||||||
<div class="qr-box">
|
|
||||||
<div id="qr-exchange"></div>
|
|
||||||
<div class="qr-label">Add exchange in wallet</div>
|
|
||||||
</div>
|
|
||||||
<a class="cta" id="open-exchange" href="taler://add-exchange/exchange.hacktivism.ch/">
|
|
||||||
Open in wallet app →
|
|
||||||
</a>
|
</a>
|
||||||
<p class="meta">taler://add-exchange/exchange.hacktivism.ch/</p>
|
<a class="app-btn"
|
||||||
|
href="https://f-droid.org/en/packages/net.taler.wallet.fdroid/"
|
||||||
|
target="_blank" rel="noopener noreferrer">
|
||||||
|
Android · F-Droid
|
||||||
|
</a>
|
||||||
|
<a class="app-btn ios"
|
||||||
|
href="https://apps.apple.com/app/taler-wallet/id6463440117"
|
||||||
|
target="_blank" rel="noopener noreferrer">
|
||||||
|
iOS · App Store
|
||||||
|
</a>
|
||||||
|
<a class="app-btn hub"
|
||||||
|
href="https://wallet.taler.net/"
|
||||||
|
target="_blank" rel="noopener noreferrer">
|
||||||
|
All platforms · wallet.taler.net
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ========== STEP 2 ========== -->
|
<!-- ========== STEP 2: one-step withdraw-exchange ========== -->
|
||||||
<section class="step-card step-money" aria-labelledby="step2-title">
|
<section class="step-card step-money" aria-labelledby="step2-title">
|
||||||
<h2 id="step2-title"><span class="step-num">2</span> Get the money</h2>
|
<h2 id="step2-title"><span class="step-num">2</span> Withdraw GOA</h2>
|
||||||
<p class="step-tagline">Withdraw GOA into the wallet you just set up.</p>
|
<p class="step-tagline">One-step: add exchange + withdraw</p>
|
||||||
<div class="step-body">
|
<div class="step-body">
|
||||||
<ol>
|
|
||||||
<li>Scan this second QR with the <strong>same wallet</strong>.</li>
|
|
||||||
<li>Default amount is <code>GOA:10</code> — confirm in the wallet.</li>
|
|
||||||
<li>If the wallet waits on a bank transfer: leave it open a moment — demo withdrawals are auto-confirmed.</li>
|
|
||||||
</ol>
|
|
||||||
<div class="qr-box">
|
<div class="qr-box">
|
||||||
<div id="qr-withdraw"></div>
|
<div id="qr-withdraw-exchange"></div>
|
||||||
<div class="qr-label" id="qr-withdraw-label">Withdraw GOA:10</div>
|
<div class="qr-label">Scan or open in wallet</div>
|
||||||
</div>
|
</div>
|
||||||
<a class="cta teal" id="open-wallet" href="#">Open withdraw in wallet →</a>
|
<a class="cta teal" id="open-withdraw-exchange"
|
||||||
<p id="status">Preparing withdraw QR…</p>
|
href="taler://withdraw-exchange/exchange.hacktivism.ch/">
|
||||||
<p class="meta" id="uri-line" hidden></p>
|
Open in wallet →
|
||||||
|
</a>
|
||||||
|
<p class="meta">taler://withdraw-exchange/exchange.hacktivism.ch/</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ========== FURTHER DOWN: own account ========== -->
|
<!-- ========== Optional bank UI ========== -->
|
||||||
<div class="more-section">
|
<div class="more-section">
|
||||||
<span class="more-label">Optional · own bank account</span>
|
<span class="more-label">Optional · bank UI & merchant</span>
|
||||||
<div class="more-card">
|
<div class="more-card">
|
||||||
<h2>Need your own balance or merchant setup?</h2>
|
<h2>Own bank account or shop?</h2>
|
||||||
<p>
|
<p>
|
||||||
The two steps above use a <strong>demo withdraw</strong> prepared by the bank.
|
Register in the bank UI for your own balance, or set up a shop at
|
||||||
For your own GOA balance, repeated withdraws, or receiving payments as a merchant,
|
<a href="https://taler.hacktivism.ch/" style="color:#f0c86a">taler.hacktivism.ch</a>.
|
||||||
create an account:
|
|
||||||
</p>
|
</p>
|
||||||
<ol>
|
|
||||||
<li>Register in the bank UI (username + password).</li>
|
|
||||||
<li>Get a credit (transfer / ops) — new accounts start at <code>GOA:0</code>.</li>
|
|
||||||
<li>Log in → <strong>Withdraw</strong> (wallet still needs the exchange from step 1).</li>
|
|
||||||
<li>To accept payments: set up a shop at
|
|
||||||
<a href="https://taler.hacktivism.ch/" style="color:#f0c86a">taler.hacktivism.ch</a>.</li>
|
|
||||||
</ol>
|
|
||||||
<div class="more-qr">
|
<div class="more-qr">
|
||||||
<div class="qr-box">
|
<div class="qr-box">
|
||||||
<div id="qr-webui"></div>
|
<div id="qr-webui"></div>
|
||||||
|
|
@ -548,7 +571,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="more-actions">
|
<div class="more-actions">
|
||||||
<a class="cta-sec" href="/webui/">Open bank UI (register / login) →</a>
|
<a class="cta-sec" href="/webui/">Open bank UI →</a>
|
||||||
<a class="cta-sec merchant" href="https://taler.hacktivism.ch/">Merchant backend →</a>
|
<a class="cta-sec merchant" href="https://taler.hacktivism.ch/">Merchant backend →</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -572,17 +595,8 @@
|
||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
var WEBUI = "https://bank.hacktivism.ch/webui/";
|
var WEBUI = "https://bank.hacktivism.ch/webui/";
|
||||||
var ADD_EXCHANGE = "taler://add-exchange/exchange.hacktivism.ch/";
|
/* taler-ops one-step: add exchange + start withdraw */
|
||||||
var statusEl = document.getElementById("status");
|
var WITHDRAW_EXCHANGE = "taler://withdraw-exchange/exchange.hacktivism.ch/";
|
||||||
var uriLine = document.getElementById("uri-line");
|
|
||||||
var openWallet = document.getElementById("open-wallet");
|
|
||||||
var label = document.getElementById("qr-withdraw-label");
|
|
||||||
|
|
||||||
function setStatus(msg, cls) {
|
|
||||||
if (!statusEl) return;
|
|
||||||
statusEl.textContent = msg;
|
|
||||||
statusEl.className = cls || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeQr(el, text) {
|
function makeQr(el, text) {
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
|
|
@ -599,35 +613,12 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
makeQr(document.getElementById("qr-exchange"), ADD_EXCHANGE);
|
makeQr(document.getElementById("qr-withdraw-exchange"), WITHDRAW_EXCHANGE);
|
||||||
makeQr(document.getElementById("qr-webui"), WEBUI);
|
makeQr(document.getElementById("qr-webui"), WEBUI);
|
||||||
|
|
||||||
var defaultAmount = "GOA:10";
|
|
||||||
|
|
||||||
function strip443(uri) {
|
|
||||||
if (!uri) return uri;
|
|
||||||
return uri.replace(/bank\.hacktivism\.ch:443/g, "bank.hacktivism.ch");
|
|
||||||
}
|
|
||||||
|
|
||||||
function useUri(uri, amount) {
|
|
||||||
if (!uri) return false;
|
|
||||||
uri = strip443(uri.trim());
|
|
||||||
var amt = amount || defaultAmount;
|
|
||||||
makeQr(document.getElementById("qr-withdraw"), uri);
|
|
||||||
if (openWallet) openWallet.href = uri;
|
|
||||||
if (uriLine) {
|
|
||||||
uriLine.hidden = false;
|
|
||||||
uriLine.textContent = uri;
|
|
||||||
}
|
|
||||||
if (label) label.textContent = "Withdraw " + amt;
|
|
||||||
setStatus("Ready — default " + amt + ". Scan with the wallet (after step 1).", "ok");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function fmtCest(unix, fallback) {
|
function fmtCest(unix, fallback) {
|
||||||
var base = "";
|
var base = "";
|
||||||
if (fallback) {
|
if (fallback) {
|
||||||
// strip trailing CEST/CET/Z if present; we append Europe/Zurich
|
|
||||||
base = String(fallback).replace(/\s*(CEST|CET|UTC|Z)\s*$/i, "").trim();
|
base = String(fallback).replace(/\s*(CEST|CET|UTC|Z)\s*$/i, "").trim();
|
||||||
} else if (unix != null && unix !== "") {
|
} else if (unix != null && unix !== "") {
|
||||||
try {
|
try {
|
||||||
|
|
@ -769,7 +760,7 @@
|
||||||
note.textContent = "";
|
note.textContent = "";
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(function (e) {
|
.catch(function () {
|
||||||
if (foot) {
|
if (foot) {
|
||||||
foot.hidden = false;
|
foot.hidden = false;
|
||||||
foot.className = "stats-foot err";
|
foot.className = "stats-foot err";
|
||||||
|
|
@ -778,38 +769,6 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
loadStats();
|
loadStats();
|
||||||
|
|
||||||
Promise.all([
|
|
||||||
fetch("withdraw.uri", { cache: "no-store" }).then(function (r) {
|
|
||||||
return r.ok ? r.text() : Promise.reject();
|
|
||||||
}),
|
|
||||||
fetch("withdraw.amount", { cache: "no-store" }).then(function (r) {
|
|
||||||
return r.ok ? r.text() : Promise.resolve(defaultAmount);
|
|
||||||
}).catch(function () { return defaultAmount; }),
|
|
||||||
fetch("stats.json", { cache: "no-store" }).then(function (r) {
|
|
||||||
return r.ok ? r.json() : null;
|
|
||||||
}).catch(function () { return null; })
|
|
||||||
])
|
|
||||||
.then(function (parts) {
|
|
||||||
var uri = (parts[0] || "").trim();
|
|
||||||
var amt = (parts[1] || defaultAmount).trim() || defaultAmount;
|
|
||||||
var st = parts[2];
|
|
||||||
if (st && st.demo && st.demo.ready === false) {
|
|
||||||
// Spent demo withdraw — prefer bank UI path
|
|
||||||
fallback("Demo withdraw already used (" + (st.demo.status || "?") + ") — open bank UI below or wait for ops refresh.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (useUri(uri, amt)) return;
|
|
||||||
fallback();
|
|
||||||
})
|
|
||||||
.catch(function () { fallback(); });
|
|
||||||
|
|
||||||
function fallback(msg) {
|
|
||||||
makeQr(document.getElementById("qr-withdraw"), WEBUI);
|
|
||||||
if (openWallet) openWallet.href = WEBUI;
|
|
||||||
if (label) label.textContent = "Bank UI (no demo withdraw)";
|
|
||||||
setStatus(msg || "No demo withdraw right now — use optional bank account below.", "err");
|
|
||||||
}
|
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue