EU payment processor and Algorand EURD wallet platform with x402 micropayments (Quantoz + on-chain Algorand).
| Component | Purpose |
|---|---|
| Android wallet | Watch-only Quantoz buyer wallet, EURD opt-in, SEPA top-up, x402 Test Lab (3 scenarios + QR scan) |
| Backend | Wallet balances, merchant portal, auto-redeem, x402 scenarios, guardrails |
| TypeScript SDK | @armsves/x402 — withGuardedPayment / withEurPayment |
Default demo buyer account: PIGVDELP (Quantoz managed, guardrails enforced)
Default merchant wallet: UTBXAKBRMXYMQ4AIDOBYP45Q4TCQVU5PEIWIP6HJWVE667JB4HYKDWIQ2U
cd backend
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .envEdit .env:
QUANTOZ_API_KEY— required for scenarios 1–2X402_BUYER_MNEMONIC— required for scenario 3 (on-chain Algorand x402). Wallet must hold mainnet ALGO (fees) and be opted into EURD (1221682136).
Run:
uvicorn app.main:app --host 0.0.0.0 --port 8080Useful URLs:
- Merchant portal: http://localhost:8080/
- x402 scenarios (web): http://localhost:8080/scenarios
- QR checkout page: http://localhost:8080/pay-qr
- API docs: http://localhost:8080/docs
Reset demo guardrails after testing:
curl -X POST "http://localhost:8080/api/v1/x402/guardrails/reset?buyerAccount=PIGVDELP"See android/README.md. Summary:
# Set sdk.dir + backend URL in android/local.properties (see local.properties.example)
cd android
./gradlew :app:assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apkOn a physical phone, set algoeupay.backend.url=http://YOUR_PC_LAN_IP:8080 (not 10.0.2.2).
Open the app → Agents tab → x402 Test Lab:
| Scenario | Price | How to run in app |
|---|---|---|
| 1 Online product | €0.15 | Tap Pay with x402 |
| 2 QR payment | €0.20 | Tap Scan merchant QR → scan QR from http://localhost:8080/pay-qr |
| 3 Hackathon report | €0.10 | Tap Pay with x402 (on-chain EURD via backend mnemonic) |
Guardrails: max 3 payments, max €1.00 total per buyer account.
cd sdk/typescript && npm install && npm run build
BACKEND_URL=http://localhost:8080 node examples/scenarios.mjsimport { withGuardedPayment } from "@armsves/x402";
const fetch = withGuardedPayment(globalThis.fetch, {
backendUrl: "http://localhost:8080",
buyerAccount: "PIGVDELP",
});
await fetch("http://localhost:8080/api/v1/x402/scenarios/online-product");
await fetch("http://localhost:8080/api/v1/x402/scenarios/hackathon-report");Scenarios 1–2 (Quantoz):
- Client calls protected resource →
402 Payment Required+ challenge - Client calls
POST /api/v1/x402/paywith{ buyerAccount, challenge, scenario } - Backend pays via Quantoz (guardrails checked) and returns
xPaymentheader value - Client retries resource with
X-PAYMENTheader → content unlocked
Scenario 3 (on-chain Algorand x402):
- Same 402 challenge (Algorand exact, EURD on mainnet)
POST /api/v1/x402/paysigns the payment group only (does not submit)GET /api/v1/x402/scenarios/hackathon-reportwithX-PAYMENT→ backend verify + settle via embedded facilitator → report JSON +X-PAYMENT-RESPONSE
Uses x402-avm (verify/settle aligned with Algorand x402 demo).
AlgoEuPay/
├── android/ # Kotlin Compose wallet + x402 Test Lab
├── backend/ # FastAPI + Quantoz + x402 + auto-redeem
├── sdk/typescript/ # @armsves/x402 npm package
└── README.md # this file
- android/README.md — build, install, wallet, SEPA top-up, x402 scenarios
- backend/README.md — API, merchant portal, env vars, auto-redeem
- sdk/README.md — npm SDK, guardrails, examples