release 1.18.3: Bank withdraw wording (was ATM for CHF-style note amounts)

Rename user-facing e2e "ATM withdraw" to "Bank withdraw". The ladder
amounts (20/50/100/200/…) were labeled ATM because they match typical
CHF cash-note sizes (Bankomat), not because anything hits a physical ATM.
Keep E2E_ATM_MAX as alias of E2E_BANK_WITHDRAW_MAX; keep e2e.atm-* group ids.
This commit is contained in:
Hernâni Marques 2026-07-19 09:06:06 +02:00
parent 4bdb08bf3c
commit efb9047a67
No known key found for this signature in database
GPG key ID: CB5738652768F7E9
9 changed files with 58 additions and 55 deletions

View file

@ -66,7 +66,7 @@ Legend:
| **Seen** | Android endless spinner; GOA `bank.hacktivism.ch` withdraw; fixed in app branch `fix/bank-withdraw-auto-exchange` | | **Seen** | Android endless spinner; GOA `bank.hacktivism.ch` withdraw; fixed in app branch `fix/bank-withdraw-auto-exchange` |
| **Area** | **core** / **cli** | | **Area** | **core** / **cli** |
| **Problem** | Withdraw URI names an exchange the wallet has never added → stuck loading / empty exchange list. CLI requires explicit `exchanges add` + `update` + `accept-tos` every fresh DB. | | **Problem** | Withdraw URI names an exchange the wallet has never added → stuck loading / empty exchange list. CLI requires explicit `exchanges add` + `update` + `accept-tos` every fresh DB. |
| **Workaround** | e2e always adds exchange before ATM ladder; Android needs ensureExchange-style fix. | | **Workaround** | e2e always adds exchange before bank withdraw ladder; Android needs ensureExchange-style fix. |
| **Wanted** | CLI/core: on `accept-uri` withdraw, **auto-add** exchange from URI/bank details (`allowCompletion`), then surface ToS if needed in one command. | | **Wanted** | CLI/core: on `accept-uri` withdraw, **auto-add** exchange from URI/bank details (`allowCompletion`), then surface ToS if needed in one command. |
--- ---
@ -87,7 +87,7 @@ Legend:
| | | | | |
|--|--| |--|--|
| **Seen** | e2e uses bank admin + ATM create; ladder/gui-chain reimplement explorer mint in Python | | **Seen** | e2e uses bank admin + bank withdraw create; ladder/gui-chain reimplement explorer mint in Python |
| **Area** | **cli** / **ops** | | **Area** | **cli** / **ops** |
| **Problem** | Automation always hand-rolls Basic auth → token → `POST …/withdrawals``taler_withdraw_uri`. Easy to get wrong (auth header, amount currency). | | **Problem** | Automation always hand-rolls Basic auth → token → `POST …/withdrawals``taler_withdraw_uri`. Easy to get wrong (auth header, amount currency). |
| **Workaround** | Shared Python in `goa-chain` / ladder / e2e; secrets files. | | **Workaround** | Shared Python in `goa-chain` / ladder / e2e; secrets files. |

View file

@ -262,7 +262,7 @@ Other domains: never SSH. Optional **e2e** aborts cleanly on login/KYC.
| | Local (koopa) | Remote | | | Local (koopa) | Remote |
|--|---------------|--------| |--|---------------|--------|
| **ATM withdraw** | 20 · 50 · 100 · 200 · **4200** (paivana) | 10 · 20 · 50 | | **Bank withdraw** | 20 · 50 · 100 · 200 · **4200** (paivana) | 10 · 20 · 50 |
| **Pay ladder** | 0.01 … 10 | 0.01 … 1 | | **Pay ladder** | 0.01 … 10 | 0.01 … 1 |
| **Paivana** | HTTP paywall + template pay **GOA:4200** (`goa-shop` / `paivana`) | skipped | | **Paivana** | HTTP paywall + template pay **GOA:4200** (`goa-shop` / `paivana`) | skipped |
@ -338,8 +338,8 @@ Amounts use exchange **`alt_unit_names`** (Kilo-GOA, Mega-GOA, …) with the bas
**GOA value in parentheses**: **GOA value in parentheses**:
```text ```text
[INFO] coins after-ATM — amount_circ=2 Kilo-GOA (GOA:2000) [INFO] coins after-bank-wd — amount_circ=2 Kilo-GOA (GOA:2000)
[INFO] coins after-ATM — denoms_in_circ 1 Kilo-GOA (GOA:1000)×2 (=2 Kilo-GOA (GOA:2000)) [INFO] coins after-bank-wd — denoms_in_circ 1 Kilo-GOA (GOA:1000)×2 (=2 Kilo-GOA (GOA:2000))
== ladder · rung 12 GOA:1000000 · 1 Mega-GOA (GOA:1000000) == == ladder · rung 12 GOA:1000000 · 1 Mega-GOA (GOA:1000000) ==
``` ```
@ -370,7 +370,7 @@ snapshotted via SSH whenever the stack is under load:
| Phase | When | | Phase | When |
|-------|------| |-------|------|
| **inside** | end of container status | | **inside** | end of container status |
| **e2e** | before work · after ATM withdraws · after payments · after shop · e2e-end (+ delta) | | **e2e** | before work · after bank withdraws · after payments · after shop · e2e-end (+ delta) |
| **ladder** | before first rung · after last rung (+ delta + timing overall) | | **ladder** | before first rung · after last rung (+ delta + timing overall) |
```bash ```bash

View file

@ -97,10 +97,10 @@ SSH: `KOOPA_SSH` (default `koopa`), then `KOOPA_SSH_FALLBACKS` when LAN is unrea
| Group | Checks | | Group | Checks |
|-------|--------| |-------|--------|
| **e2e.prereq-** | wallet-cli, currency, budgets, secrets, public reachability | | **e2e.prereq-** | wallet-cli, currency, budgets, secrets, public reachability |
| **e2e.load-** | host/container load snapshots (before / after ATM / after pay) | | **e2e.load-** | host/container load snapshots (before / after bank withdraw / after pay) |
| **e2e.bank-** | account, credit, withdraw ops | | **e2e.bank-** | account, credit, withdraw ops |
| **e2e.wallet-** | exchange + ToS, wallet setup | | **e2e.wallet-** | exchange + ToS, wallet setup |
| **e2e.atm-** | ATM withdraw ladder rungs | | **e2e.atm-** (group id; UI says Bank withdraw) | bank withdraw ladder rungs |
| **e2e.settle-** | wallet settlement wait / spendable balance | | **e2e.settle-** | wallet settlement wait / spendable balance |
| **e2e.pay-** | variable payments | | **e2e.pay-** | variable payments |
| **e2e.shop-** | GOA shop product catalog pays | | **e2e.shop-** | GOA shop product catalog pays |
@ -109,7 +109,7 @@ SSH: `KOOPA_SSH` (default `koopa`), then `KOOPA_SSH_FALLBACKS` when LAN is unrea
| **e2e.report-** | final tallies | | **e2e.report-** | final tallies |
When filing an issue, quote the full id + label, e.g. When filing an issue, quote the full id + label, e.g.
`e2e.atm-03 ATM withdraw 5 GOA · bank confirmed, wallet empty`. `e2e.atm-03 Bank withdraw 5 GOA · bank confirmed, wallet empty`.
--- ---

View file

@ -1 +1 @@
1.18.2 1.18.3

View file

@ -17,6 +17,7 @@ Git tags: `vMAJOR.FEATURE.FIX` (e.g. `v1.8.0`). File `VERSION` omits the `v` pre
| Tag | Date (UTC) | Notes | | Tag | Date (UTC) | Notes |
|-----|------------|--------| |-----|------------|--------|
| **v1.18.3** | 2026-07-19 | **Bugfix / wording:** e2e user-facing **ATM withdraw****Bank withdraw** (amounts still CHF-style cash-note ladder 20/50/100/200/… — “ATM” was only a metaphor for those note sizes, not a physical ATM). Env: `E2E_BANK_WITHDRAW_MAX` (legacy alias `E2E_ATM_MAX`). Internal group id `e2e.atm-*` kept for check-id stability. |
| **v1.18.2** | 2026-07-19 | **Bugfix:** never publish / accept **stale mon HTML assets** — refuse pre-1.15.8 box-drawing sticky JS in site-gen + generated pages; monpages ERROR on public pages still carrying that JS or teed `SyntaxWarning: invalid escape sequence`; purge `site-gen/__pycache__` after suite reset; convert with `PYTHONWARNINGS=error::SyntaxWarning`. | | **v1.18.2** | 2026-07-19 | **Bugfix:** never publish / accept **stale mon HTML assets** — refuse pre-1.15.8 box-drawing sticky JS in site-gen + generated pages; monpages ERROR on public pages still carrying that JS or teed `SyntaxWarning: invalid escape sequence`; purge `site-gen/__pycache__` after suite reset; convert with `PYTHONWARNINGS=error::SyntaxWarning`. |
| **v1.18.1** | 2026-07-19 | **Bugfix:** (1) mon HTML sticky/err counts honor French badges **ERREUR** / **AVERT** (were plain → 0 errors on FP pages); (2) `stage-lfp` + `INSIDE_PODMAN=1` uses **host-podman** (no empty `INSIDE_SSH` fail); (3) reaffirm filter JS has no box-glyph/`\\-` regex (charCodeAt only — kills SyntaxWarning “geheimsprache” noise). | | **v1.18.1** | 2026-07-19 | **Bugfix:** (1) mon HTML sticky/err counts honor French badges **ERREUR** / **AVERT** (were plain → 0 errors on FP pages); (2) `stage-lfp` + `INSIDE_PODMAN=1` uses **host-podman** (no empty `INSIDE_SSH` fail); (3) reaffirm filter JS has no box-glyph/`\\-` regex (charCodeAt only — kills SyntaxWarning “geheimsprache” noise). |
| **v1.18.0** | 2026-07-19 | **Feature:** mattermost — client compatibility matrix: **mobile**, **desktop**, **vendor support** floors (default ≥10.11.0, ERROR) + **web** WARN on EOL; env `MATTERMOST_DESKTOP/SUPPORT_MIN_SERVER`, `MATTERMOST_CLIENT_CHECK`. | | **v1.18.0** | 2026-07-19 | **Feature:** mattermost — client compatibility matrix: **mobile**, **desktop**, **vendor support** floors (default ≥10.11.0, ERROR) + **web** WARN on EOL; env `MATTERMOST_DESKTOP/SUPPORT_MIN_SERVER`, `MATTERMOST_CLIENT_CHECK`. |

View file

@ -8,7 +8,7 @@ source "$ROOT/lib.sh"
# shellcheck source=metrics.sh # shellcheck source=metrics.sh
source "$ROOT/metrics.sh" source "$ROOT/metrics.sh"
: "${E2E_TIMEOUT:=180}" # ATM ladder + wirewatch lag needs room (was 55 — too tight) : "${E2E_TIMEOUT:=180}" # Bank withdraw ladder + wirewatch lag needs room (was 55 — too tight)
: "${E2E_PAY_SECS:=22}" # hard reserve for handle-uri + settle (do not starve pay) : "${E2E_PAY_SECS:=22}" # hard reserve for handle-uri + settle (do not starve pay)
: "${E2E_SETTLE_ROUNDS:=18}" : "${E2E_SETTLE_ROUNDS:=18}"
: "${E2E_SETTLE_SLEEP:=3}" : "${E2E_SETTLE_SLEEP:=3}"
@ -226,18 +226,20 @@ except Exception: print("")' 2>/dev/null || true)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Variable amounts # Variable amounts
# Withdraw = typical ATM notes only (Bankomat): 20 / 50 / 100 / 200 … # Withdraw = typical bank cash-note amounts (CHF-style: was called ATM): 20 / 50 / 100 / 200 …
# Pay = several smaller purchase amounts # Pay = several smaller purchase amounts
# Env: # Env:
# E2E_WITHDRAW_VALUES="20 50 100" # bare numbers → prefixed with CUR # E2E_WITHDRAW_VALUES="20 50 100" # bare numbers → prefixed with CUR
# E2E_PAY_VALUES="0.01 0.05 0.5 1 2 5" # E2E_PAY_VALUES="0.01 0.05 0.5 1 2 5"
# E2E_VARIABLE=0 # single fixed WITHDRAW_AMT / PAY_AMT # E2E_VARIABLE=0 # single fixed WITHDRAW_AMT / PAY_AMT
# E2E_ATM_MAX=N # try at most N ATM withdraws (budget) # E2E_BANK_WITHDRAW_MAX=N # try at most N bank withdraws (budget)
# E2E_ATM_MAX=N # legacy alias of E2E_BANK_WITHDRAW_MAX
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
: "${E2E_VARIABLE:=1}" : "${E2E_VARIABLE:=1}"
: "${E2E_ATM_MAX:=5}" : "${E2E_BANK_WITHDRAW_MAX:=${E2E_ATM_MAX:-5}}"
E2E_ATM_MAX="${E2E_ATM_MAX:-$E2E_BANK_WITHDRAW_MAX}" # legacy alias
if [ "$E2E_REMOTE" = "1" ]; then if [ "$E2E_REMOTE" = "1" ]; then
# remote: still ATM-shaped; TESTPAYSAN needs larger notes for shop pays # remote: still bank cash-note shaped; TESTPAYSAN needs larger notes for shop pays
if [ "$CUR" = "TESTPAYSAN" ]; then if [ "$CUR" = "TESTPAYSAN" ]; then
: "${E2E_WITHDRAW_VALUES:=20 50}" : "${E2E_WITHDRAW_VALUES:=20 50}"
# farmer shop template face values (oeufs-6=5, fromage=8.5, jus=6) # farmer shop template face values (oeufs-6=5, fromage=8.5, jus=6)
@ -247,7 +249,7 @@ if [ "$E2E_REMOTE" = "1" ]; then
: "${E2E_PAY_VALUES:=0.01 0.05 0.1 1}" : "${E2E_PAY_VALUES:=0.01 0.05 0.1 1}"
fi fi
else else
# local GOA: classic ATM notes + 4200 for paivana paywall template # local GOA: classic bank cash-note amounts + 4200 for paivana paywall template
: "${E2E_WITHDRAW_VALUES:=20 50 100 200 4200}" : "${E2E_WITHDRAW_VALUES:=20 50 100 200 4200}"
: "${E2E_PAY_VALUES:=0.01 0.05 0.1 0.5 1 2 5 10}" : "${E2E_PAY_VALUES:=0.01 0.05 0.1 0.5 1 2 5 10}"
fi fi
@ -284,7 +286,7 @@ if [ "$E2E_VARIABLE" != "1" ]; then
fi fi
fi fi
# Credit = sum of planned ATM withdraws + small buffer for fees # Credit = sum of planned Bank withdraws + small buffer for fees
CREDIT_AMT=$(python3 -c ' CREDIT_AMT=$(python3 -c '
import sys import sys
cur=sys.argv[1] cur=sys.argv[1]
@ -301,7 +303,7 @@ print("%s:%g" % (cur, s + buf))
WITHDRAW_AMT=$(printf '%s' "$WITHDRAW_LIST" | awk '{print $1}') WITHDRAW_AMT=$(printf '%s' "$WITHDRAW_LIST" | awk '{print $1}')
PAY_AMT=$(printf '%s' "$PAY_LIST" | awk '{print $1}') PAY_AMT=$(printf '%s' "$PAY_LIST" | awk '{print $1}')
# More wall time when running ATM ladder # More wall time when running Bank withdraw ladder
if [ "$E2E_VARIABLE" = "1" ]; then if [ "$E2E_VARIABLE" = "1" ]; then
n_w=$(printf '%s' "$WITHDRAW_LIST" | wc -w | tr -d ' ') n_w=$(printf '%s' "$WITHDRAW_LIST" | wc -w | tr -d ' ')
n_p=$(printf '%s' "$PAY_LIST" | wc -w | tr -d ' ') n_p=$(printf '%s' "$PAY_LIST" | wc -w | tr -d ' ')
@ -309,9 +311,9 @@ if [ "$E2E_VARIABLE" = "1" ]; then
if [ "${E2E_TIMEOUT}" -lt "$need" ]; then if [ "${E2E_TIMEOUT}" -lt "$need" ]; then
E2E_TIMEOUT=$need E2E_TIMEOUT=$need
fi fi
# cap ATM attempts but always keep CUR:4200 if listed (paivana) # cap bank withdraw attempts but always keep CUR:4200 if listed (paivana)
WITHDRAW_LIST=$( WITHDRAW_LIST=$(
printf '%s' "$WITHDRAW_LIST" | tr ' ' '\n' | awk -v max="$E2E_ATM_MAX" -v big="${CUR}:4200" ' printf '%s' "$WITHDRAW_LIST" | tr ' ' '\n' | awk -v max="$E2E_BANK_WITHDRAW_MAX" -v big="${CUR}:4200" '
NF==0 { next } NF==0 { next }
$0==big { has=1; next } $0==big { has=1; next }
{ small[++n]=$0 } { small[++n]=$0 }
@ -413,7 +415,7 @@ else
fi fi
info "e2e mode" "$([ "$E2E_REMOTE" = "1" ] && echo "remote/public domain (no SSH)" || echo "local koopa stack")" info "e2e mode" "$([ "$E2E_REMOTE" = "1" ] && echo "remote/public domain (no SSH)" || echo "local koopa stack")"
info "currency" "$CUR" info "currency" "$CUR"
info "ATM withdraw ladder" "$WITHDRAW_LIST (credit $CREDIT_AMT)" info "Bank withdraw ladder" "$WITHDRAW_LIST (credit $CREDIT_AMT)"
info "pay ladder" "$PAY_LIST" info "pay ladder" "$PAY_LIST"
info "e2e budget" "${E2E_TIMEOUT}s" info "e2e budget" "${E2E_TIMEOUT}s"
@ -863,7 +865,7 @@ else
warn "wallet accept ToS" "$(tail -c 80 "$SCRATCH/ex-tos.out" | tr '\n' ' ')" warn "wallet accept ToS" "$(tail -c 80 "$SCRATCH/ex-tos.out" | tr '\n' ' ')"
fi fi
fi fi
# Empty wallet baseline before ATM / pay load # Empty wallet baseline before bank withdraw / pay load
metrics_report_coins "wallet-ready" || true metrics_report_coins "wallet-ready" || true
wd_status() { wd_status() {
@ -901,15 +903,15 @@ fake_incoming_speedup() {
fi fi
} }
# One ATM-style withdraw: create → accept → select → confirm → settle # One bank withdraw: create → accept → select → confirm → settle
# returns 0 on wallet balance increase, 1 on soft fail (ladder continues) # returns 0 on wallet balance increase, 1 on soft fail (ladder continues)
e2e_one_withdraw() { e2e_one_withdraw() {
WITHDRAW_AMT="$1" WITHDRAW_AMT="$1"
local tag local tag
tag=$(printf '%s' "$WITHDRAW_AMT" | tr '.:' '__') tag=$(printf '%s' "$WITHDRAW_AMT" | tr '.:' '__')
section "e2e · ATM withdraw $WITHDRAW_AMT · $(format_amount_alt "$WITHDRAW_AMT")" section "e2e · Bank withdraw $WITHDRAW_AMT · $(format_amount_alt "$WITHDRAW_AMT")"
e2e_over && { warn "ATM withdraw" "budget exhausted — skip $WITHDRAW_AMT"; return 1; } e2e_over && { warn "Bank withdraw" "budget exhausted — skip $WITHDRAW_AMT"; return 1; }
metrics_report_coins "before-ATM-${tag}" || true metrics_report_coins "before-bank-wd-${tag}" || true
curl -sS -m 15 -o "$SCRATCH/wd-$tag.json" -H "Authorization: Bearer $UT" \ curl -sS -m 15 -o "$SCRATCH/wd-$tag.json" -H "Authorization: Bearer $UT" \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
@ -919,10 +921,10 @@ e2e_one_withdraw() {
URI=$(python3 -c 'import json;d=json.load(open("'"$SCRATCH"'/wd-'"$tag"'.json"));print(d.get("taler_withdraw_uri") or "")' 2>/dev/null || true) URI=$(python3 -c 'import json;d=json.load(open("'"$SCRATCH"'/wd-'"$tag"'.json"));print(d.get("taler_withdraw_uri") or "")' 2>/dev/null || true)
URI_CLEAN=$(python3 -c 'import json;u=json.load(open("'"$SCRATCH"'/wd-'"$tag"'.json")).get("taler_withdraw_uri") or "";print(u.replace(":443/","/"))' 2>/dev/null || true) URI_CLEAN=$(python3 -c 'import json;u=json.load(open("'"$SCRATCH"'/wd-'"$tag"'.json")).get("taler_withdraw_uri") or "";print(u.replace(":443/","/"))' 2>/dev/null || true)
if [ -z "$WID" ] || [ -z "$URI_CLEAN" ]; then if [ -z "$WID" ] || [ -z "$URI_CLEAN" ]; then
warn "ATM withdraw $WITHDRAW_AMT" "create failed — $(head -c 80 "$SCRATCH/wd-$tag.json" | tr '\n' ' ')" warn "Bank withdraw $WITHDRAW_AMT" "create failed — $(head -c 80 "$SCRATCH/wd-$tag.json" | tr '\n' ' ')"
return 1 return 1
fi fi
ok "ATM withdrawal created $WITHDRAW_AMT ($WID)" ok "Bank withdrawal created $WITHDRAW_AMT ($WID)"
cp "$SCRATCH/wd-$tag.json" "$SCRATCH/wd.json" cp "$SCRATCH/wd-$tag.json" "$SCRATCH/wd.json"
USE_URI="$URI" USE_URI="$URI"
@ -933,7 +935,7 @@ e2e_one_withdraw() {
&& wcli withdraw accept-uri --exchange "${EXCHANGE_PUBLIC}/" "$URI_CLEAN" >"$SCRATCH/accept-$tag.out" 2>&1; then && wcli withdraw accept-uri --exchange "${EXCHANGE_PUBLIC}/" "$URI_CLEAN" >"$SCRATCH/accept-$tag.out" 2>&1; then
ok "wallet accept $WITHDRAW_AMT (no :443)" ok "wallet accept $WITHDRAW_AMT (no :443)"
else else
warn "ATM withdraw $WITHDRAW_AMT" "accept-uri failed — $(tail -c 100 "$SCRATCH/accept-$tag.out" | tr '\n' ' ')" warn "Bank withdraw $WITHDRAW_AMT" "accept-uri failed — $(tail -c 100 "$SCRATCH/accept-$tag.out" | tr '\n' ' ')"
return 1 return 1
fi fi
cp "$SCRATCH/accept-$tag.out" "$SCRATCH/accept.out" cp "$SCRATCH/accept-$tag.out" "$SCRATCH/accept.out"
@ -975,7 +977,7 @@ else:
fi fi
fi fi
if [ "$st" != "selected" ] && [ "$st" != "confirmed" ]; then if [ "$st" != "selected" ] && [ "$st" != "confirmed" ]; then
warn "ATM withdraw $WITHDRAW_AMT" "not selected (status=${st:-?})" warn "Bank withdraw $WITHDRAW_AMT" "not selected (status=${st:-?})"
return 1 return 1
fi fi
if [ "$st" != "confirmed" ]; then if [ "$st" != "confirmed" ]; then
@ -984,32 +986,32 @@ else:
"$BANK/accounts/${USER}/withdrawals/${WID}/confirm") "$BANK/accounts/${USER}/withdrawals/${WID}/confirm")
case "$code" in case "$code" in
200|204) ok "bank confirm $WITHDRAW_AMT" ;; 200|204) ok "bank confirm $WITHDRAW_AMT" ;;
*) warn "ATM withdraw $WITHDRAW_AMT" "confirm HTTP $code"; return 1 ;; *) warn "Bank withdraw $WITHDRAW_AMT" "confirm HTTP $code"; return 1 ;;
esac esac
fi fi
fake_incoming_speedup fake_incoming_speedup
# Short per-ATM settle: poll balance + bank transfer_done only (never run-until-done) # Short per-withdraw settle: poll balance + bank transfer_done only (never run-until-done)
local ok_bal=0 r av xfer local ok_bal=0 r av xfer
for r in 1 2 3 4 5 6 8 10; do for r in 1 2 3 4 5 6 8 10; do
wcli_bal_snap "$SCRATCH/bal-$tag.out" || wcli balance >"$SCRATCH/bal-$tag.out" 2>&1 || true wcli_bal_snap "$SCRATCH/bal-$tag.out" || wcli balance >"$SCRATCH/bal-$tag.out" 2>&1 || true
av=$(wallet_avail_num "$SCRATCH/bal-$tag.out") av=$(wallet_avail_num "$SCRATCH/bal-$tag.out")
if python3 -c "import sys; sys.exit(0 if float(sys.argv[1]) > 0 else 1)" "$av" 2>/dev/null; then if python3 -c "import sys; sys.exit(0 if float(sys.argv[1]) > 0 else 1)" "$av" 2>/dev/null; then
ok_bal=1 ok_bal=1
ok "wallet funded after ATM $WITHDRAW_AMT" "avail=${CUR}:${av}" ok "wallet funded after bank withdraw $WITHDRAW_AMT" "avail=${CUR}:${av}"
info "balance" "$(fmt_bal "$SCRATCH/bal-$tag.out")" info "balance" "$(fmt_bal "$SCRATCH/bal-$tag.out")"
break break
fi fi
xfer=$(curl -sS -m 8 "$BANK/taler-integration/withdrawal-operation/${WID}" 2>/dev/null \ xfer=$(curl -sS -m 8 "$BANK/taler-integration/withdrawal-operation/${WID}" 2>/dev/null \
| python3 -c 'import json,sys; d=json.load(sys.stdin); print(d.get("transfer_done"), d.get("status"))' 2>/dev/null || echo "?") | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d.get("transfer_done"), d.get("status"))' 2>/dev/null || echo "?")
if echo "$xfer" | grep -qi True; then if echo "$xfer" | grep -qi True; then
ok "ATM $WITHDRAW_AMT bank transfer_done" "wallet avail=${CUR}:${av} ($xfer) — no run-until-done" ok "Bank withdraw $WITHDRAW_AMT bank transfer_done" "wallet avail=${CUR}:${av} ($xfer) — no run-until-done"
ok_bal=1 ok_bal=1
break break
fi fi
sleep 2 sleep 2
done done
metrics_report_coins "after-ATM-${tag}" || true metrics_report_coins "after-bank-wd-${tag}" || true
if [ "$ok_bal" = "1" ]; then if [ "$ok_bal" = "1" ]; then
metrics_record_flow withdrawn "$WITHDRAW_AMT" || true metrics_record_flow withdrawn "$WITHDRAW_AMT" || true
return 0 return 0
@ -1017,10 +1019,10 @@ else:
# Bank side often already confirmed — treat as timing lag, not hard fail # Bank side often already confirmed — treat as timing lag, not hard fail
st=$(wd_status) st=$(wd_status)
if [ "$st" = "confirmed" ]; then if [ "$st" = "confirmed" ]; then
warn "ATM withdraw $WITHDRAW_AMT" "bank confirmed; wallet not funded yet (settlement timing — will recheck later)" warn "Bank withdraw $WITHDRAW_AMT" "bank confirmed; wallet not funded yet (settlement timing — will recheck later)"
return 2 return 2
fi fi
warn "ATM withdraw $WITHDRAW_AMT" "no wallet balance yet (status=${st:-?})" warn "Bank withdraw $WITHDRAW_AMT" "no wallet balance yet (status=${st:-?})"
return 1 return 1
} }
@ -1336,7 +1338,7 @@ sys.exit(1)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
set_group atm set_group atm
section "e2e · ATM withdraw ladder" section "e2e · Bank withdraw ladder"
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
WITHDRAW_OK=0 WITHDRAW_OK=0
WITHDRAW_OK_N=0 WITHDRAW_OK_N=0
@ -1344,7 +1346,7 @@ WITHDRAW_LAG_N=0
WITHDRAW_FAIL_N=0 WITHDRAW_FAIL_N=0
WITHDRAW_REPORT="" WITHDRAW_REPORT=""
for WITHDRAW_AMT in $WITHDRAW_LIST; do for WITHDRAW_AMT in $WITHDRAW_LIST; do
e2e_over && { warn "ATM ladder" "time budget low — stopping more ATM withdraws (not a protocol error)"; break; } e2e_over && { warn "Bank withdraw ladder" "time budget low — stopping more Bank withdraws (not a protocol error)"; break; }
set +e set +e
e2e_one_withdraw "$WITHDRAW_AMT" e2e_one_withdraw "$WITHDRAW_AMT"
wc=$? wc=$?
@ -1365,26 +1367,26 @@ for WITHDRAW_AMT in $WITHDRAW_LIST; do
;; ;;
esac esac
done done
info "ATM withdraw summary" "$WITHDRAW_REPORT (ok=$WITHDRAW_OK_N lag=$WITHDRAW_LAG_N fail=$WITHDRAW_FAIL_N)" info "Bank withdraw summary" "$WITHDRAW_REPORT (ok=$WITHDRAW_OK_N lag=$WITHDRAW_LAG_N fail=$WITHDRAW_FAIL_N)"
set_group load set_group load
section "e2e · load snapshot (after ATM withdraws)" section "e2e · load snapshot (after Bank withdraws)"
metrics_report_load "${METRICS_DIR}/load-after-withdraw.json" "after-withdraw" || true metrics_report_load "${METRICS_DIR}/load-after-withdraw.json" "after-withdraw" || true
cp -f "${METRICS_DIR}/load-after-withdraw.json" "${METRICS_DIR}/load-after.json" 2>/dev/null || true cp -f "${METRICS_DIR}/load-after-withdraw.json" "${METRICS_DIR}/load-after.json" 2>/dev/null || true
metrics_report_coins "after-ATM-ladder" || true metrics_report_coins "after-bank-wd-ladder" || true
# Settlement catch-up: bank may have confirmed while wallet was still empty # Settlement catch-up: bank may have confirmed while wallet was still empty
set_group settle set_group settle
section "e2e · wallet settlement (timing)" section "e2e · wallet settlement (timing)"
if ! wait_wallet_balance 0 "${E2E_SETTLE_ROUNDS}" "${E2E_SETTLE_SLEEP}"; then if ! wait_wallet_balance 0 "${E2E_SETTLE_ROUNDS}" "${E2E_SETTLE_SLEEP}"; then
if [ "$WITHDRAW_LAG_N" -gt 0 ] || [ "$WITHDRAW_OK_N" -gt 0 ]; then if [ "$WITHDRAW_LAG_N" -gt 0 ] || [ "$WITHDRAW_OK_N" -gt 0 ]; then
warn "settlement timing" "ATM path reached bank confirm (lag=$WITHDRAW_LAG_N ok=$WITHDRAW_OK_N) but wallet empty after wait — TIME lag, not protocol error" warn "settlement timing" "bank withdraw path reached bank confirm (lag=$WITHDRAW_LAG_N ok=$WITHDRAW_OK_N) but wallet empty after wait — TIME lag, not protocol error"
fi fi
fi fi
av_now=$(wallet_avail_num) av_now=$(wallet_avail_num)
if python3 -c "import sys; sys.exit(0 if float(sys.argv[1]) > 0 else 1)" "$av_now" 2>/dev/null; then if python3 -c "import sys; sys.exit(0 if float(sys.argv[1]) > 0 else 1)" "$av_now" 2>/dev/null; then
WITHDRAW_OK=1 WITHDRAW_OK=1
if [ "$WITHDRAW_OK_N" = "0" ]; then if [ "$WITHDRAW_OK_N" = "0" ]; then
warn "settlement timing" "coins arrived after ATM ladder (${CUR}:${av_now}) — earlier 'FAIL' was timing lag" warn "settlement timing" "coins arrived after Bank withdraw ladder (${CUR}:${av_now}) — earlier 'FAIL' was timing lag"
WITHDRAW_REPORT="${WITHDRAW_REPORT} → late-OK avail=${CUR}:${av_now}" WITHDRAW_REPORT="${WITHDRAW_REPORT} → late-OK avail=${CUR}:${av_now}"
fi fi
ok "spendable balance for payments" "${CUR}:${av_now}" ok "spendable balance for payments" "${CUR}:${av_now}"
@ -1403,7 +1405,7 @@ else
WITHDRAW_OK=1 WITHDRAW_OK=1
warn "settlement timing" "coins present after dig wait (${CUR}:${av_now}) — timing, not blocker" warn "settlement timing" "coins present after dig wait (${CUR}:${av_now}) — timing, not blocker"
else else
blocker "withdraw-settle" "no spendable ${CUR} after ATM ladder + settle wait ($WITHDRAW_LIST)" blocker "withdraw-settle" "no spendable ${CUR} after Bank withdraw ladder + settle wait ($WITHDRAW_LIST)"
section "e2e · report" section "e2e · report"
info "WITHDRAW" "$WITHDRAW_REPORT — no coins after extended wait" info "WITHDRAW" "$WITHDRAW_REPORT — no coins after extended wait"
info "PAY" "SKIPPED (no spendable balance after settle wait)" info "PAY" "SKIPPED (no spendable balance after settle wait)"
@ -1596,7 +1598,7 @@ set_group paivana
section "e2e · paivana paywall (template GOA:4200)" section "e2e · paivana paywall (template GOA:4200)"
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Public paywall: https://paivana.hacktivism.ch → 302 to merchant template "paivana". # Public paywall: https://paivana.hacktivism.ch → 302 to merchant template "paivana".
# Requires spendable ≥ 4200 GOA (ATM ladder includes GOA:4200 by default). # Requires spendable ≥ 4200 GOA (Bank withdraw ladder includes GOA:4200 by default).
: "${PAIVANA_PUBLIC:=https://paivana.hacktivism.ch}" : "${PAIVANA_PUBLIC:=https://paivana.hacktivism.ch}"
: "${E2E_PAIVANA:=1}" : "${E2E_PAIVANA:=1}"
: "${E2E_PAIVANA_TEMPLATE:=paivana}" : "${E2E_PAIVANA_TEMPLATE:=paivana}"
@ -1630,11 +1632,11 @@ else
;; ;;
esac esac
# Ensure wallet can cover 4200 (extra ATM if ladder did not fund enough) # Ensure wallet can cover 4200 (extra bank withdraw if ladder did not fund enough)
pay_need=$(python3 -c 'import sys; print(float(sys.argv[1].split(":",1)[-1]))' "$E2E_PAIVANA_AMOUNT" 2>/dev/null || echo 4200) pay_need=$(python3 -c 'import sys; print(float(sys.argv[1].split(":",1)[-1]))' "$E2E_PAIVANA_AMOUNT" 2>/dev/null || echo 4200)
av_now=$(wallet_avail_num) av_now=$(wallet_avail_num)
if ! python3 -c "import sys; sys.exit(0 if float(sys.argv[1]) + 1e-9 >= float(sys.argv[2]) else 1)" "$av_now" "$pay_need" 2>/dev/null; then if ! python3 -c "import sys; sys.exit(0 if float(sys.argv[1]) + 1e-9 >= float(sys.argv[2]) else 1)" "$av_now" "$pay_need" 2>/dev/null; then
info "paivana" "avail ${CUR}:${av_now} < ${pay_need}ATM withdraw ${E2E_PAIVANA_AMOUNT}" info "paivana" "avail ${CUR}:${av_now} < ${pay_need}Bank withdraw ${E2E_PAIVANA_AMOUNT}"
e2e_over && warn "paivana" "budget low before 4200 withdraw" e2e_over && warn "paivana" "budget low before 4200 withdraw"
set +e set +e
e2e_one_withdraw "$E2E_PAIVANA_AMOUNT" e2e_one_withdraw "$E2E_PAIVANA_AMOUNT"
@ -1687,7 +1689,7 @@ fi
set_group report set_group report
section "e2e · report" section "e2e · report"
info "user" "$USER" info "user" "$USER"
info "ATM withdraws" "$WITHDRAW_REPORT" info "Bank withdraws" "$WITHDRAW_REPORT"
info "payments" "$PAY_REPORT" info "payments" "$PAY_REPORT"
info "shop" "${SHOP_REPORT:-(n/a)}" info "shop" "${SHOP_REPORT:-(n/a)}"
info "paivana" "${PAIVANA_REPORT:-(n/a)}" info "paivana" "${PAIVANA_REPORT:-(n/a)}"

View file

@ -1316,7 +1316,7 @@ if [ "${LOCAL_STACK:-1}" = "1" ] || [ -n "${BANK_PUBLIC:-}" ]; then
fi fi
;; ;;
404|405|501) 404|405|501)
# GOA bank landing mints demo-withdraw.json; stage TESTPAYSAN uses ATM/wallet guide only # GOA bank landing mints demo-withdraw.json; stage TESTPAYSAN uses bank withdraw/wallet guide only
if [ "${EXPECT_CURRENCY:-}" = "GOA" ] || [ "${LOCAL_STACK:-0}" = "1" ]; then if [ "${EXPECT_CURRENCY:-}" = "GOA" ] || [ "${LOCAL_STACK:-0}" = "1" ]; then
fail "landing bank demo-withdraw" "HTTP $dw_code (want 200)" fail "landing bank demo-withdraw" "HTTP $dw_code (want 200)"
else else

4
lib.sh
View file

@ -62,9 +62,9 @@ fi
# Merchant portal /private API: instance ids must be lowercase or you get odd 401s. # Merchant portal /private API: instance ids must be lowercase or you get odd 401s.
# (Display names may use capitals; path segment /instances/{id}/ must not.) # (Display names may use capitals; path segment /instances/{id}/ must not.)
MERCHANT_INSTANCE=$(printf '%s' "${MERCHANT_INSTANCE}" | tr '[:upper:]' '[:lower:]') MERCHANT_INSTANCE=$(printf '%s' "${MERCHANT_INSTANCE}" | tr '[:upper:]' '[:lower:]')
: "${WITHDRAW_AMT:=GOA:20}" # single-shot fallback; e2e ladder uses ATM notes : "${WITHDRAW_AMT:=GOA:20}" # single-shot fallback; e2e ladder uses bank cash-note amounts
: "${PAY_AMT:=GOA:0.01}" : "${PAY_AMT:=GOA:0.01}"
: "${CREDIT_AMT:=GOA:4700}" # covers ATM ladder 20+50+100+200+4200 (paivana) : "${CREDIT_AMT:=GOA:4700}" # covers bank withdraw ladder 20+50+100+200+4200 (paivana)
: "${TIMEOUT:=12}" : "${TIMEOUT:=12}"
: "${E2E_TIMEOUT:=55}" # whole e2e budget; skip rest when exceeded (e2e raises as needed) : "${E2E_TIMEOUT:=55}" # whole e2e budget; skip rest when exceeded (e2e raises as needed)
: "${E2E_PAY_SECS:=22}" # dedicated seconds for pay handle-uri (avoid Alarm clock) : "${E2E_PAY_SECS:=22}" # dedicated seconds for pay handle-uri (avoid Alarm clock)

View file

@ -293,7 +293,7 @@ if [ "${LOCAL_STACK:-1}" != "1" ]; then
SKIP_SSH=1 SKIP_SSH=1
fi fi
# Remote: no SSH; ATM withdraw ladder set in check_e2e (smaller notes) # Remote: no SSH; bank withdraw ladder set in check_e2e (smaller notes)
if [ "${LOCAL_STACK}" != "1" ]; then if [ "${LOCAL_STACK}" != "1" ]; then
E2E_FAKE_INCOMING=0 E2E_FAKE_INCOMING=0
E2E_REMOTE=1 E2E_REMOTE=1
@ -307,7 +307,7 @@ export EXPECT_CURRENCY SKIP_SSH LOCAL_STACK TALER_DOMAIN_PROBE CHECK_LANDING
export TALER_DOMAIN_FROM_CLI="${TALER_DOMAIN_FROM_CLI:-0}" export TALER_DOMAIN_FROM_CLI="${TALER_DOMAIN_FROM_CLI:-0}"
export DOMAIN_SET="${DOMAIN_SET:-0}" export DOMAIN_SET="${DOMAIN_SET:-0}"
export WITHDRAW_AMT PAY_AMT CREDIT_AMT MERCHANT_INSTANCE export WITHDRAW_AMT PAY_AMT CREDIT_AMT MERCHANT_INSTANCE
export E2E_FAKE_INCOMING E2E_REMOTE E2E_VARIABLE E2E_ATM_MAX export E2E_FAKE_INCOMING E2E_REMOTE E2E_VARIABLE E2E_ATM_MAX E2E_BANK_WITHDRAW_MAX
export E2E_WITHDRAW_VALUES E2E_PAY_VALUES E2E_USE_TEMPLATES E2E_TEMPLATE_MAP export E2E_WITHDRAW_VALUES E2E_PAY_VALUES E2E_USE_TEMPLATES E2E_TEMPLATE_MAP
export PAIVANA_PUBLIC E2E_PAIVANA E2E_PAIVANA_TEMPLATE E2E_PAIVANA_AMOUNT E2E_PAIVANA_INSTANCE export PAIVANA_PUBLIC E2E_PAIVANA E2E_PAIVANA_TEMPLATE E2E_PAIVANA_AMOUNT E2E_PAIVANA_INSTANCE
export INSIDE_PROFILE INSIDE_SSH export INSIDE_PROFILE INSIDE_SSH
@ -431,7 +431,7 @@ _progress_estimate_phase() {
versions) n=35 ;; versions) n=35 ;;
sanity) n=35 ;; sanity) n=35 ;;
server) n=20 ;; server) n=20 ;;
# e2e: ATM ladder emits many INFO lines (coins before/after each note) # e2e: bank withdraw ladder emits many INFO lines (coins before/after each note)
e2e) n=240 ;; e2e) n=240 ;;
ladder|goa-ladder) n=120 ;; ladder|goa-ladder) n=120 ;;
auth401) n=70 ;; auth401) n=70 ;;