Pay anywhere. Even when the network can't.
A Touch 'n Go e-wallet extension that enables offline peer-to-peer NFC payments — no internet required. An on-device AI model determines a safe offline spending limit, Ed25519-signed tokens prove the transaction, and everything settles automatically when either party reconnects.
Hackathon: TNG Digital FINHACK 2026 | Track: Financial Inclusion | Clouds: AWS + Alibaba Cloud
Cashless adoption stalls when connectivity is unreliable — rural areas, transit underground, packed event venues, and disaster scenarios. A user with a TNG balance still falls back to physical cash because the wallet cannot transact without a network. This friction hits hardest for the financially underserved: gig workers, hawkers, students on prepaid data, and rural micro-merchants.
TAP 1 Merchant (Aida) ──────────────────────> Payer (Faiz)
SELECT AID [F0544E47504159]
PUT-REQUEST ──> payment request delivered to Faiz's phone
Pay Confirm screen appears automatically
[Faiz reviews amount, approves with biometric, JWS is signed]
TAP 2 Payer (Faiz) ───────────────────────> Merchant (Aida)
PUT-DATA ──> signed Ed25519 JWS token delivered
GET-ACK ──> Aida signs sha256(jws) as audit receipt
No server call. No internet. Both phones in airplane mode. Settlement happens on reconnect.
An XGBoost model trained on AWS SageMaker analyzes each user's transaction history and outputs a safe offline spending limit — how much of their cached balance they can spend without overdraft risk. The model is converted to TF Lite and runs fully on-device (< 2 MB). Alibaba PAI-EAS serves online refresh. The limit is recomputed every sync.
Every offline payment produces an Ed25519-signed JWS token. The private key lives in the Android Keystore — never in Dart or SharedPreferences. Biometric authorization is required per signing. When either party reconnects, tokens are submitted to the settlement service, which performs:
- Ed25519 signature verification
- Idempotent double-spend guard — DynamoDB conditional put on
nonce_seen - Balance debit on Alibaba Tablestore
- Push notification to both parties
| Layer | AWS | Alibaba Cloud |
|---|---|---|
| ML training | SageMaker + S3 | — |
| ML runtime | — | PAI-EAS + OSS |
| Token ledger | DynamoDB + Lambda | — |
| Wallet balance | — | Tablestore + FC |
| Auth | Cognito + KMS | — |
| User PII | — | RDS KL + Tablestore |
| Event bridge | EventBridge | EventBridge |
Cross-cloud calls are mTLS + HMAC body-signed. PII never leaves Alibaba Cloud KL region.
flowchart TD
subgraph Mobile["📱 Android Phone (Flutter)"]
direction TB
UI[Flutter UI\nRiverpod]
TFLite["TF Lite Scorer\n(on-device AI)"]
Keystore["Android Keystore\nEd25519 private key"]
HCE["HCE Service\n(Kotlin)"]
Outbox[("Offline Outbox\nDrift SQLite")]
UI --> TFLite & Keystore & HCE & Outbox
end
PeerPhone["📱 Peer Phone\n(same app)"]
HCE -- "NFC ISO 14443-4\nAPDU chunks\n(AID F0544E47504159)" --> PeerPhone
subgraph Alibaba["☁️ Alibaba Cloud — ap-southeast-3 (Kuala Lumpur)"]
direction TB
APIGW[API Gateway]
FC["Function Compute\n· balance/sync\n· device register\n· settle ingest\n· score refresh"]
Tablestore[("Tablestore\nwallets · devices\nusers · cache")]
OSS[("OSS\nTF Lite models\npublic keys")]
RDS[("ApsaraDB RDS\ntxn history")]
EAS["PAI-EAS\nXGBoost inference"]
AliEB[EventBridge]
Push[Mobile Push]
AKMS[KMS]
APIGW --> FC
FC --> Tablestore & OSS & RDS & EAS & AliEB & Push
end
subgraph AWS["☁️ AWS — ap-southeast-1 (Singapore)"]
direction TB
Cognito["Cognito\nJWT issuer"]
Lambda["Lambda\n· verify Ed25519\n· settle tokens\n· double-spend guard"]
Dynamo[("DynamoDB\ntoken_ledger\nnonce_seen")]
SageMaker["SageMaker\nXGBoost training"]
S3[("S3\nmodel artifacts\ndata lake")]
AWSEB[EventBridge]
AWSKMS[KMS]
Lambda --> Dynamo & AWSKMS
SageMaker --> S3
end
Mobile -- "HTTPS + Cognito JWT" --> APIGW
FC -- "B4 · JWKS verify" --> Cognito
S3 -- "B1 · model publish" --> OSS
AliEB -- "B2 · settle batch" --> AWSEB --> Lambda
Lambda -- "B3 · result" --> AliEB --> FC
Cross-cloud boundaries: B1 model publish (AWS S3 → Alibaba OSS) · B2 settlement request (Alibaba → AWS) · B3 settlement result (AWS → Alibaba) · B4 JWT verification (Alibaba FC → AWS Cognito JWKS) · All bridge calls are mTLS + HMAC body-signed.
| Area | Technology |
|---|---|
| Mobile | Flutter (Android), Kotlin HCE, Android Keystore |
| Cryptography | Ed25519 (API 33+), JWS (EdDSA / tng-offline-tx+jws) |
| NFC | Android HCE — AID F0544E47504159 |
| ML | XGBoost → TF Lite via Treelite, on-device inference |
| Backend | Python (AWS Lambda + Alibaba FC) |
| Infra | Terraform (AWS) + Terraform/ROS (Alibaba) |
| State | Flutter Riverpod, Drift (local SQLite) |
.
├── lib/ # Flutter app (Riverpod, go_router)
│ ├── features/ # home, pay, receive, request, history …
│ ├── domain/ # credit scorer, offline pay policy
│ └── core/ # crypto, NFC platform channel, identity
├── android/ # Kotlin HCE service + Keystore platform channel
├── backend/ # AWS Lambda handlers + Alibaba FC handlers
├── ml/ # SageMaker training, synthetic data, EAS server
├── infra/
│ ├── aws/ # Terraform: DynamoDB, Lambda, Cognito, KMS, EventBridge
│ └── alibaba/ # Terraform: FC, Tablestore, OSS, RDS, PAI-EAS
├── test/ # Flutter unit + widget tests
├── docs/ # Full spec (see index below)
└── dist/ # Pre-built web demo
- Flutter 3.x with Android SDK (minSdk 26; Ed25519 requires API 33+)
- Python 3.11+
- Two Android devices or emulators for NFC testing
python3 backend/server.pyflutter run \
--dart-define=API_BASE_URL=http://10.0.2.2:3000/v1 \
--dart-define=API_BEARER_TOKEN=demo-token \
--dart-define=DEVICE_ID=did:tng:device:demoflutter test
python3 -m pytest backend/tests tests
(cd android && ./gradlew app:compileDebugKotlin)See docs/13-deployment.md for the full Terraform workflow, environment variables, secrets, and current deployment status.
- Open Request tab → enter amount and memo → tap Request via NFC
- Hold phone to payer's phone — payment request transfers over NFC
- Screen switches to Waiting for payer…
- Pay Confirm screen appears automatically after tap 1
- Review amount and merchant — tap Approve → biometric prompt
- Hold phone to merchant's phone — signed JWS transfers over NFC
- Receipt shown immediately; settlement queued for reconnect
Both parties receive a push notification confirming the settled balance once either device goes online.
| Mechanism | Implementation |
|---|---|
| Key storage | Android Keystore, setUserAuthenticationRequired(true) |
| Signing | Ed25519 per-transaction, biometric-gated (except ≤ RM 5) |
| Double-spend | DynamoDB conditional put on nonce_seen — single path, no bypass |
| Token expiry | JWS valid for 72 h; payment request TTL 300 s |
| Cross-cloud auth | mTLS + HMAC body signing on all bridge webhooks |
| KYC caps | Enforced server-side only — never trust client-claimed tier |
| ML model OTA | Sigstore signature verified before swap; reject on mismatch |
KYC spending tiers:
| Tier | Per token | Per 24 h |
|---|---|---|
| 0 — Phone OTP | RM 20 | RM 50 |
| 1 — IC last 4 | RM 50 | RM 150 |
| 2 — eKYC | RM 250 | RM 500 |
Full threat model: docs/10-security-threat-model.md
| Doc | Covers |
|---|---|
| 00 — Overview | Problem, value prop, success metrics, judging map |
| 01 — Architecture | System diagram, multi-cloud split, data flows |
| 02 — User Flows | Screens, wireframes, two-tap walkthrough |
| 03 — Token Protocol | JWS schema, Ed25519, NFC APDU, anti-replay |
| 04 — Credit Score ML | Features, model, training, OTA, on-device inference |
| 05 — AWS Services | SageMaker, Lambda, DynamoDB, Cognito, KMS, EventBridge |
| 06 — Alibaba Services | PAI-EAS, OSS, FC, Tablestore, RDS, KMS, Mobile Push |
| 07 — Mobile App | Flutter layout, HCE, key gen, Drift schema |
| 08 — Backend API | REST contracts and JSON schemas |
| 09 — Data Model | All datastore schemas and key designs |
| 10 — Security | STRIDE table, key lifecycle, KYC tiers |
| 11 — Demo & Test Plan | 4-min demo script, TS-01..TS-21 test scenarios |
| 12 — Build Tasks | Engineering task list, DoD, dependency DAG |
| 13 — Deployment | IaC layout, env vars, secrets, CI, rollback |
| Area | Status |
|---|---|
| Flutter offline request/pay/receive flow | Working locally |
| Android NFC + Keystore path | Working locally |
| Local backend settlement + replay protection | Verified (pytest) |
| AWS Lambda + API Gateway deploy | Deployable via Terraform |
| Alibaba FC + HTTP trigger deploy | Deployable via Terraform |
| Alibaba PAI-EAS | Needs cloud apply |
| Live AWS ↔ Alibaba smoke test | Pending |
| Two-device NFC dry run vs deployed backend | Pending |
Built at TNG Digital FINHACK 2026 for the Financial Inclusion track.
See Idea.md for the original brainstorm and HackathonInfo.md for judging criteria.