#!/bin/bash # Credit a bank user by transferring from admin (creates regional GOA via admin debit). # Run as root on koopa host (bank on 127.0.0.1:9012). # # Usage: # credit-account.sh [USERNAME] [AMOUNT] # credit-account.sh explorer GOA:1000 set -euo pipefail BANK="${BANK_URL:-http://127.0.0.1:9012}" TO_USER="${1:-explorer}" AMOUNT="${2:-GOA:1000}" ADMIN_PASS="${BANK_ADMIN_PASS:-}" if [ -z "$ADMIN_PASS" ] && [ -f /root/bank-admin-password.txt ]; then ADMIN_PASS=$(tr -d '\n' &2; exit 1; } W=$(mktemp -d) trap 'rm -rf "$W"' EXIT echo '{"scope":"readwrite"}' >"$W/tok.json" curl -sS -m 15 -u "admin:${ADMIN_PASS}" \ -H 'Content-Type: application/json' \ -d @"$W/tok.json" \ "${BANK}/accounts/admin/token" >"$W/tok.out" TOKEN=$(python3 -c "import json;print(json.load(open('$W/tok.out')).get('access_token',''))") [ -n "$TOKEN" ] || { echo "admin token failed:"; cat "$W/tok.out"; exit 1; } # payto for x-taler-bank regional accounts PAYTO="payto://x-taler-bank/bank.hacktivism.ch/${TO_USER}?receiver-name=${TO_USER}&message=credit-from-admin" python3 - "$AMOUNT" "$PAYTO" "$W/tx.json" <<'PY' import json, sys, os amount, payto, out = sys.argv[1], sys.argv[2], sys.argv[3] # ShortHashCode: Crockford base32 of 32 random bytes (52 chars) _ALPH = "0123456789ABCDEFGHJKMNPQRSTVWXYZ" def crockford32(data: bytes) -> str: n = int.from_bytes(data, "big") bits = len(data) * 8 outc = [] while bits > 0: bits -= 5 outc.append(_ALPH[(n >> bits) & 31] if bits >= 0 else _ALPH[(n << (-bits)) & 31]) if bits <= 0: break # pad to full groups s = "".join(outc) # simpler bit stream return None def crock32(b: bytes) -> str: bits = 0 val = 0 outc = [] for byte in b: val = (val << 8) | byte bits += 8 while bits >= 5: bits -= 5 outc.append(_ALPH[(val >> bits) & 31]) if bits: outc.append(_ALPH[(val << (5 - bits)) & 31]) return "".join(outc) uid = crock32(os.urandom(32)) json.dump({"payto_uri": payto, "amount": amount, "request_uid": uid}, open(out, "w")) print("request_uid", uid, "len", len(uid)) PY echo "POST admin -> $TO_USER amount=$AMOUNT" curl -sS -m 15 \ -H "Authorization: Bearer ${TOKEN}" \ -H 'Content-Type: application/json' \ -d @"$W/tx.json" \ "${BANK}/accounts/admin/transactions" | tee "$W/tx.out" echo # show balances for u in admin "$TO_USER"; do curl -sS -m 10 -u "admin:${ADMIN_PASS}" \ -H 'Content-Type: application/json' -d '{"scope":"readonly"}' \ "${BANK}/accounts/admin/token" >"$W/rtok" 2>/dev/null || true done # re-token readonly and print target balance echo '{"scope":"readonly"}' >"$W/rtok.json" # admin can GET any account curl -sS -m 10 -H "Authorization: Bearer ${TOKEN}" \ "${BANK}/accounts/${TO_USER}" | tee "$W/acc.out" echo python3 -c " import json d=json.load(open('$W/acc.out')) b=d.get('balance') or {} print('RESULT', '${TO_USER}', 'balance=', b.get('amount'), b.get('credit_debit_indicator')) print('debit_threshold=', d.get('debit_threshold')) "