96 lines
3.1 KiB
Bash
Executable file
96 lines
3.1 KiB
Bash
Executable file
#!/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' </root/bank-admin-password.txt)
|
|
fi
|
|
[ -n "$ADMIN_PASS" ] || { echo "Need BANK_ADMIN_PASS or /root/bank-admin-password.txt" >&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'))
|
|
"
|