docs: bank shared withdraw, auto-account, merchant shop landing
Document bank landing layout, demo-withdraw + auto-account APIs (goa-bank-acc-*, balance 0), explorer-only auto-confirm, QR_Taler, and merchant shop/stats behaviour. Refresh taler-bank script index.
This commit is contained in:
parent
930716a94d
commit
6a212d14c6
3 changed files with 153 additions and 48 deletions
|
|
@ -1,38 +1,78 @@
|
||||||
# Bank landing (`bank.hacktivism.ch`)
|
# Bank landing (`bank.hacktivism.ch`)
|
||||||
|
|
||||||
English intro for **GOA exploration**: put coins in a GNU Taler wallet, optionally
|
English intro for **GOA exploration** (badge: **Intergalactic · GOA · no IBAN**):
|
||||||
open your own bank account, and point merchants at `taler.hacktivism.ch`.
|
put coins in a GNU Taler wallet, optionally open your own bank account, and
|
||||||
|
point merchants at `taler.hacktivism.ch`.
|
||||||
|
|
||||||
| Public URL | What |
|
| Public URL | What |
|
||||||
|------------|------|
|
|------------|------|
|
||||||
| `https://bank.hacktivism.ch/` · `/intro/` | Landing (nginx in bank container → host **9013**, Caddy) |
|
| `https://bank.hacktivism.ch/` · `/intro/` | Landing (nginx in bank container → host **9013**, Caddy) |
|
||||||
| `https://bank.hacktivism.ch/intro/stats.json` | **Live stats** (written *inside* bank container) |
|
| `https://bank.hacktivism.ch/intro/stats.json` | **Live stats** (written *inside* bank container) |
|
||||||
|
| `https://bank.hacktivism.ch/intro/demo-withdraw.json` | Mint **shared-pool** (`explorer`) withdraw URI |
|
||||||
|
| `https://bank.hacktivism.ch/intro/auto-account.json` | Auto-create **personal** bank user (credentials once; balance **GOA:0**) |
|
||||||
| `https://bank.hacktivism.ch/webui/` | libeufin-bank SPA (register · login · withdraw) when libeufin is up on **9012** |
|
| `https://bank.hacktivism.ch/webui/` | libeufin-bank SPA (register · login · withdraw) when libeufin is up on **9012** |
|
||||||
| `https://exchange.hacktivism.ch/` | Exchange (ToS `/terms`, keys `/keys`) |
|
| `https://exchange.hacktivism.ch/` | Exchange (ToS `/terms`, keys `/keys`) |
|
||||||
| `https://taler.hacktivism.ch/` | Merchant backend |
|
| `https://taler.hacktivism.ch/` | Merchant backend |
|
||||||
|
|
||||||
|
## Page layout (top → bottom)
|
||||||
|
|
||||||
|
1. Hero (badge, short shared-account line)
|
||||||
|
2. **Get the wallet** — Play / F-Droid / iOS / web hub (Chrome · Firefox · Opera · Ubuntu Touch; gold+blue icons, [taler.net wallet](https://www.taler.net/de/wallet.html))
|
||||||
|
3. **Withdraw GOA** — QR_Taler frame (blue ring + logo), open CTA, live pool balance note
|
||||||
|
4. **How the shared account works** — collapsed fold (click to expand)
|
||||||
|
5. **Optional · bank UI & GOA shop** — collapsed fold: auto-create account + credentials + QR_Taler for bank UI; mini shop
|
||||||
|
6. **GOA flow** stats
|
||||||
|
7. **Performance**
|
||||||
|
8. Footer
|
||||||
|
|
||||||
## User flow (documented on the page)
|
## User flow (documented on the page)
|
||||||
|
|
||||||
### Primary path (works without your own bank account)
|
### Primary path (works without your own bank account)
|
||||||
|
|
||||||
1. **Install wallet** — Android (Play Store / F-Droid) and iOS (App Store), plus hub `wallet.taler.net`.
|
1. **Install wallet** — Android (Play / F-Droid), iOS, Ubuntu Touch (via Waydroid + Android wallet), web (Chrome/Firefox/Opera on taler.net).
|
||||||
2. **One QR / link** — live `taler://withdraw/…` from the **community-shared** bank pool (`explorer`).
|
2. **One QR / link** — live `taler://withdraw/…` from the **community-shared** bank pool (`explorer`).
|
||||||
Minted via `GET /intro/demo-withdraw.json` (or fallback `withdraw.uri`).
|
Minted via `GET /intro/demo-withdraw.json` (or fallback `withdraw.uri`).
|
||||||
Auto-confirm finishes the bank side so coins reach the wallet.
|
Auto-confirm finishes the bank side so coins reach the wallet.
|
||||||
|
3. **Surprising balance note** — shows live `balance_explorer` from `stats.json`
|
||||||
|
(“pool holds GOA:… (shared, but also yours)”).
|
||||||
|
|
||||||
### Optional paths
|
QR encoding matches merchant shop popup (**QR_Taler**): animated `#0042B3` conic
|
||||||
|
ring, off-DOM PNG, center `qr-logo.svg` (`shop-pay.css` classes). Label text:
|
||||||
|
**Scan in wallet**.
|
||||||
|
|
||||||
- **Own bank account** — register in `/webui/`, then withdraw (private balance).
|
### Optional: personal bank account (auto-created)
|
||||||
- **`taler://withdraw-exchange/…`** — only useful if you already have a bank balance to withdraw from.
|
|
||||||
|
|
||||||
### How it works (community pool)
|
In the optional fold:
|
||||||
|
|
||||||
|
1. User clicks **Create my bank account**.
|
||||||
|
2. Browser calls `GET /intro/auto-account.json` (no form fields).
|
||||||
|
3. Server registers a new libeufin user via public `POST /accounts`.
|
||||||
|
4. UI shows **username / password / balance GOA:0** once (“created for you”;
|
||||||
|
not stored for recovery).
|
||||||
|
5. Username shape: **`goa-bank-acc-<16-hex>`**.
|
||||||
|
6. QR_Taler + link open `/webui/` so the user can log in with those credentials.
|
||||||
|
|
||||||
|
Balance **starts at zero** — not the shared `explorer` pool.
|
||||||
|
|
||||||
|
### How the shared pool works
|
||||||
|
|
||||||
1. Shared account `explorer` is pre-funded with GOA.
|
1. Shared account `explorer` is pre-funded with GOA.
|
||||||
2. Each click creates a **one-shot** withdrawal from that pool (not a personal login).
|
2. Each demo withdraw is a **one-shot** op from that pool (not a personal login).
|
||||||
3. Wallet accepts the URI; bank auto-confirm + exchange settle → coins in the app.
|
3. Wallet accepts the URI; **auto-confirm only for `explorer`** (see
|
||||||
4. Balance is **shared**; demo amounts only.
|
`auto-confirm-withdrawals.sh`).
|
||||||
|
4. Pool balance is communal; amounts you withdraw are yours in the wallet.
|
||||||
|
|
||||||
Helpers: `scripts/taler-bank/demo-withdraw-api.py`, `refresh-demo-withdraw.sh`, `auto-confirm-withdrawals.sh`, `install-demo-withdraw-api.sh`.
|
### Helpers
|
||||||
|
|
||||||
|
| Script | Role |
|
||||||
|
|--------|------|
|
||||||
|
| `scripts/taler-bank/demo-withdraw-api.py` | Loopback HTTP **:19096** — `/demo-withdraw.json` + `/auto-account.json` |
|
||||||
|
| `scripts/taler-bank/install-demo-withdraw-api.sh` | Copy into bank container, nginx locations, start API + auto-confirm loop |
|
||||||
|
| `scripts/taler-bank/auto-confirm-withdrawals.sh` | Confirm **explorer-only** withdrawals when status=`selected` |
|
||||||
|
| `scripts/taler-bank/refresh-demo-withdraw.sh` | Refresh static `withdraw.uri` (no python) |
|
||||||
|
| `configs/bank-landing/nginx-landing.conf` | `/intro/demo-withdraw.json`, `/intro/auto-account.json` proxies |
|
||||||
|
|
||||||
|
Needs **python3** in the bank container for `demo-withdraw-api.py`.
|
||||||
|
|
||||||
### CLI sketch (fresh wallet DB)
|
### CLI sketch (fresh wallet DB)
|
||||||
|
|
||||||
|
|
@ -62,11 +102,12 @@ Stats are **not** computed on the laptop or host browser. A small script runs
|
||||||
### What the page shows
|
### What the page shows
|
||||||
|
|
||||||
- **Bank accounts** — registered accounts (libeufin `GET /accounts`, admin)
|
- **Bank accounts** — registered accounts (libeufin `GET /accounts`, admin)
|
||||||
- **Wallets involved** — unique reserve pubs from Taler withdrawal debits (≈ individual wallet withdraws)
|
- **Wallets involved** — unique reserve pubs from Taler withdrawal debits
|
||||||
- **Withdraws / total out** — customer debit withdrawals only (exchange mirror skipped)
|
- **Withdraws / bank credits** — flow amounts (exchange mirror skipped where noted)
|
||||||
- **Last withdraws** — recent list with amount, time (**CEST** / `Europe/Zurich`), bank username
|
- **Last withdraws** — recent list with amount, time (**CEST** / `Europe/Zurich`)
|
||||||
- **Last 24h / 7d** — count · amount
|
- **Last 24h / 7d** — amount
|
||||||
- Footer: updated time (CEST), user-account count, accounts that funded withdraws — **no** “demo QR / pool explorer”
|
- **`balance_explorer`** — live shared-pool balance (shown on withdraw step)
|
||||||
|
- Performance probes + container RSS (bottom of page)
|
||||||
|
|
||||||
### `stats.json` shape (abridged)
|
### `stats.json` shape (abridged)
|
||||||
|
|
||||||
|
|
@ -74,27 +115,18 @@ Stats are **not** computed on the laptop or host browser. A small script runs
|
||||||
{
|
{
|
||||||
"ok": true,
|
"ok": true,
|
||||||
"currency": "GOA",
|
"currency": "GOA",
|
||||||
"generated_at": "2026-07-09T18:55Z",
|
"generated_at": "2026-07-10T20:35+02:00",
|
||||||
"account": "explorer",
|
"balance_explorer": "GOA:960",
|
||||||
"balance": "GOA:960",
|
"bank_accounts": { "total": 56, "users": 55 },
|
||||||
|
"wallets": { "unique_reserves": 51 },
|
||||||
"withdraws": {
|
"withdraws": {
|
||||||
"count": 4,
|
"count": 51,
|
||||||
"total_amount": "GOA:40",
|
"last_24h": { "amount": "GOA:…" },
|
||||||
"last_amount": "GOA:10",
|
"last_7d": { "amount": "GOA:…" }
|
||||||
"last_at": "2026-07-09T08:49Z",
|
|
||||||
"last_24h": { "count": 2, "amount": "GOA:20" },
|
|
||||||
"last_7d": { "count": 4, "amount": "GOA:40" }
|
|
||||||
},
|
},
|
||||||
"flow": {
|
"flow": {
|
||||||
"debits_scanned": "GOA:40",
|
"incoming": { "amount": "GOA:…", "count": 68 },
|
||||||
"credits_scanned": "GOA:1000",
|
"withdraw": { "amount": "GOA:…", "count": 51 }
|
||||||
"tx_scanned": 5
|
|
||||||
},
|
|
||||||
"demo": {
|
|
||||||
"uri": "taler://withdraw/…",
|
|
||||||
"amount": "GOA:10",
|
|
||||||
"status": "confirmed",
|
|
||||||
"ready": false
|
|
||||||
},
|
},
|
||||||
"source": "in-container landing-stats.sh"
|
"source": "in-container landing-stats.sh"
|
||||||
}
|
}
|
||||||
|
|
@ -144,22 +176,35 @@ Landing root (nginx in bank container), typically under something like
|
||||||
|
|
||||||
| File | Role |
|
| File | Role |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `index.html` | landing (steps + stats panel) |
|
| `index.html` | landing (wallet, shared withdraw, folds, stats) |
|
||||||
| `qrcode.min.js` | QR helper |
|
| `shop-pay.css` / `shop-pay.js` | GOA shop popup + **QR_Taler** frame styles |
|
||||||
|
| `qr-logo.svg` | center logo on QR_Taler frames |
|
||||||
|
| `qrcode.min.js` | QR encode helper |
|
||||||
| `stats.json` | **live stats** (from in-container script) |
|
| `stats.json` | **live stats** (from in-container script) |
|
||||||
|
| `nginx-landing.conf` | bank container nginx (**9013**) |
|
||||||
| `withdraw.uri` | current demo `taler://withdraw/…` (optional) |
|
| `withdraw.uri` | current demo `taler://withdraw/…` (optional) |
|
||||||
| `withdraw.amount` | e.g. `GOA:10` (optional) |
|
| `withdraw.amount` | e.g. `GOA:10` (optional) |
|
||||||
| `withdraw-watch.ids` | ids for auto-confirm helper (optional) |
|
| `withdraw-watch.ids` | ids for auto-confirm helper (optional) |
|
||||||
|
|
||||||
## Deploy landing HTML
|
## Deploy landing HTML + helper API
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# from laptop (example) — path depends on where nginx in the bank container reads from
|
# landing assets
|
||||||
scp koopa-admin-log/configs/bank-landing/index.html \
|
podman cp configs/bank-landing/index.html \
|
||||||
koopa-admin-log/configs/bank-landing/qrcode.min.js \
|
taler-hacktivism-bank:/var/www/bank-landing/index.html
|
||||||
hernani@koopa:/tmp/bank-landing/
|
podman cp configs/bank-landing/shop-pay.js \
|
||||||
# then copy into the bank container / host path used by nginx :9013
|
taler-hacktivism-bank:/var/www/bank-landing/shop-pay.js
|
||||||
podman cp /tmp/bank-landing/index.html taler-hacktivism-bank:/var/www/bank-landing/index.html
|
# … shop-pay.css, qr-logo.svg, qrcode.min.js as needed
|
||||||
|
|
||||||
|
# demo-withdraw + auto-account API (python3 in container)
|
||||||
|
./scripts/taler-bank/install-demo-withdraw-api.sh
|
||||||
|
# or manually:
|
||||||
|
podman cp scripts/taler-bank/demo-withdraw-api.py \
|
||||||
|
taler-hacktivism-bank:/usr/local/bin/demo-withdraw-api.py
|
||||||
|
podman cp configs/bank-landing/nginx-landing.conf \
|
||||||
|
taler-hacktivism-bank:/etc/nginx/sites-available/bank-landing
|
||||||
|
# restart: python3 /usr/local/bin/demo-withdraw-api.py on 127.0.0.1:19096
|
||||||
|
# nginx -s reload; auto-confirm-withdrawals.sh --loop
|
||||||
```
|
```
|
||||||
|
|
||||||
### Demo QR refresh (in container, no python)
|
### Demo QR refresh (in container, no python)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Merchant landing (`taler.hacktivism.ch` intro)
|
# Merchant landing (`taler.hacktivism.ch` intro)
|
||||||
|
|
||||||
Static intro for the **GOA merchant** backend.
|
Static intro for the **GOA merchant** backend (dual currency GOA + CHF).
|
||||||
|
|
||||||
| Item | Value |
|
| Item | Value |
|
||||||
|------|--------|
|
|------|--------|
|
||||||
|
|
@ -8,8 +8,32 @@ Static intro for the **GOA merchant** backend.
|
||||||
| In-container path | `/var/www/merchant-landing/` |
|
| In-container path | `/var/www/merchant-landing/` |
|
||||||
| nginx | listen **9015** (`nginx-landing.conf`) |
|
| nginx | listen **9015** (`nginx-landing.conf`) |
|
||||||
| **Host port to publish / wire** | **`9015`** → `127.0.0.1:9015` |
|
| **Host port to publish / wire** | **`9015`** → `127.0.0.1:9015` |
|
||||||
| Public path (once Caddy wired) | e.g. `https://taler.hacktivism.ch/intro/` |
|
| Public path | `https://taler.hacktivism.ch/intro/` |
|
||||||
|
|
||||||
|
## Features (page)
|
||||||
|
|
||||||
|
| Piece | Notes |
|
||||||
|
|-------|--------|
|
||||||
|
| Wallet fold | Collapsed “Get the wallet · Android / iOS / web browsers” |
|
||||||
|
| Web icons | Chrome · Firefox · Opera · Ubuntu Touch (gold+blue; [taler.net wallet](https://www.taler.net/de/wallet.html)) |
|
||||||
|
| GOA shop samples | `data-product` buttons → public template pay (`goa-shop` instance) |
|
||||||
|
| Shop pay popup | `shop-pay.js` / `shop-pay.css` — **QR_Taler** (blue ring + `qr-logo.svg`), settlement payto expandable |
|
||||||
|
| Get GOA first | Hint + link to bank; `p(l)ay` with violet `(l)` |
|
||||||
|
| Stats | Dual-currency aggregates; **recent activity** split GOA/CHF (≤5 each); refund badge violet |
|
||||||
|
| Performance | Live HTTP probes + container RSS |
|
||||||
|
|
||||||
|
Shop product ids/amounts must stay in sync with
|
||||||
|
`scripts/taler-monitoring/check_e2e.sh` → `E2E_SHOP_PRODUCTS`
|
||||||
|
(e2e random-picks **2** products per run by default).
|
||||||
|
|
||||||
## Deploy
|
## Deploy
|
||||||
|
|
||||||
See `scripts/taler-landing/deploy-landings.sh`.
|
```bash
|
||||||
|
podman cp configs/merchant-landing/index.html \
|
||||||
|
taler-hacktivism:/var/www/merchant-landing/index.html
|
||||||
|
podman cp configs/merchant-landing/shop-pay.js \
|
||||||
|
taler-hacktivism:/var/www/merchant-landing/shop-pay.js
|
||||||
|
# shop-pay.css, qr-logo.svg, qrcode.min.js as needed
|
||||||
|
```
|
||||||
|
|
||||||
|
Also see `scripts/taler-landing/deploy-landings.sh` if present.
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@ Container: **`taler-hacktivism-bank`** (libeufin-bank, GOA, **no IBAN**).
|
||||||
| `check_bank-health.sh` | `/usr/local/bin/` | libeufin-bank / any |
|
| `check_bank-health.sh` | `/usr/local/bin/` | libeufin-bank / any |
|
||||||
| `landing-stats.sh` | `/usr/local/bin/` | root (in container) — writes `/var/www/bank-landing/stats.json` |
|
| `landing-stats.sh` | `/usr/local/bin/` | root (in container) — writes `/var/www/bank-landing/stats.json` |
|
||||||
| `landing-stats-install.sh` | host only | root/podman — copies + runs + optional cron |
|
| `landing-stats-install.sh` | host only | root/podman — copies + runs + optional cron |
|
||||||
|
| `demo-withdraw-api.py` | `/usr/local/bin/` | root — loopback **:19096** |
|
||||||
|
| `install-demo-withdraw-api.sh` | host only | installs API + nginx + auto-confirm |
|
||||||
|
| `auto-confirm-withdrawals.sh` | `/usr/local/bin/` | root — **explorer-only** confirm loop |
|
||||||
|
| `refresh-demo-withdraw.sh` | `/usr/local/bin/` | refresh static `withdraw.uri` |
|
||||||
|
| `credit-account.sh` | host/ops | admin → user credit |
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|
@ -30,6 +35,37 @@ Container: **`taler-hacktivism-bank`** (libeufin-bank, GOA, **no IBAN**).
|
||||||
|
|
||||||
Details + JSON schema: `configs/bank-landing/README.md`.
|
Details + JSON schema: `configs/bank-landing/README.md`.
|
||||||
|
|
||||||
|
## Demo withdraw + auto-account API
|
||||||
|
|
||||||
|
`demo-withdraw-api.py` listens on **127.0.0.1:19096** (proxied by nginx on the landing):
|
||||||
|
|
||||||
|
| Path | Behaviour |
|
||||||
|
|------|-----------|
|
||||||
|
| `GET /demo-withdraw.json` | Mint one-shot withdraw from shared **`explorer`** pool; write `withdraw.uri` + watch ids |
|
||||||
|
| `GET /auto-account.json` | Public `POST /accounts` with generated **`goa-bank-acc-<hex>`** user + password; **balance GOA:0**; return credentials once |
|
||||||
|
|
||||||
|
Install / restart:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./install-demo-withdraw-api.sh
|
||||||
|
# Public checks:
|
||||||
|
curl -sS https://bank.hacktivism.ch/intro/demo-withdraw.json | head
|
||||||
|
curl -sS https://bank.hacktivism.ch/intro/auto-account.json | head # creates a real account
|
||||||
|
```
|
||||||
|
|
||||||
|
Requires **python3** in the bank container. Env: `BANK_URL`, `BANK_USER`/`BANK_PASS`
|
||||||
|
(or `/root/bank-explorer-password.txt`), `AMOUNT` (default `GOA:10` for shared withdraws).
|
||||||
|
|
||||||
|
### Auto-confirm (explorer only)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# loop inside container — refuses non-explorer unless ALLOW_NON_EXPLORER=1
|
||||||
|
auto-confirm-withdrawals.sh --loop 4
|
||||||
|
```
|
||||||
|
|
||||||
|
Only confirms withdrawals owned by **`explorer`** when status is `selected`
|
||||||
|
(community demo path). Does not confirm arbitrary customer withdraws.
|
||||||
|
|
||||||
## Config
|
## Config
|
||||||
|
|
||||||
See `configs/taler-hacktivism-bank/`.
|
See `configs/taler-hacktivism-bank/` and `configs/bank-landing/`.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue