A Web3 mobile wallet integrating daily financial management and crypto assets into a single platform
Walt is an application that integrates daily financial management and crypto asset management into a single platform. Users can make payments, transfers, and monitor their crypto assets all within one app.
The app is designed to reduce the complexity of using multiple separate financial applications, allowing users to manage all their financial activities more easily, efficiently, and seamlessly.
| Feature | Description |
|---|---|
| QR Payments (QRIS) | Pay at any Indonesian QRIS merchant using crypto. Users pay with LSK/ETH/POL, merchants receive IDR via Xendit settlement. |
| Crypto Asset Swap | Exchange crypto assets directly within the app with real-time rates and 0.2% fee. |
| Peer-to-Peer Transfer | Send funds to contacts with gas sponsorship via barter model. |
| NearSync (NFC) | Transfer funds to nearby users via NFC for quick face-to-face transactions. |
| Split Bill | Divide expenses among multiple people with smart contract escrow for fairness and transparency. |
Add real app screenshots/GIFs here — this is the single highest-impact addition for a portfolio. Drop images in
docs/screenshots/and reference them below.
| Home | QRIS Pay | Swap | Split Bill |
|---|---|---|---|
| add image | add image | add image | add image |
┌─────────────────────────────────────────────────────────────────────────────┐
│ WALT SYSTEM ARCHITECTURE │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Flutter │ API │ Node.js │ RPC │ Lisk │ │
│ │ Mobile App │◄───────►│ Backend │◄───────►│ Sepolia │ │
│ │ │ │ │ │ Blockchain │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │ │ │
│ │ │ │ │
│ ┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐ │
│ │ Web3Auth │ │ Xendit │ │ Smart │ │
│ │ Keys │ │ Settlement│ │ Contracts │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
All smart contracts are deployed on Lisk Sepolia Testnet (Chain ID: 4202) and implement OpenZeppelin security patterns.
| Contract | Address | Blockscout |
|---|---|---|
| CanmaSplitBillV5 | 0x998C402E2d5A55EC599C84B7B1C446732b29E5F3 |
View |
| WaltQRPayV3 | 0x4f11677bcF14FEEfD906Dd978a4E4Ad54b4Ce194 |
View |
| WaltSwapV2 | 0x31169C501C316Fa6ec2e4E483ab32C09F8337149 |
View |
| MockLSK | 0x4270A0c8676a10ab8cbe3e92bfd187d94c8f248e |
View |
| MockPOL | 0xEE412e79eB7F565Ec9e7c8A1b0a7eC27b63fbc5e |
View |
- ReentrancyGuard - Protection against reentrancy attacks
- Pausable - Emergency stop mechanism
- AccessControl - Role-based permissions (OPERATOR_ROLE, ADMIN_ROLE)
- SafeERC20 - Safe token transfer handling
- Ownable2Step - Two-step ownership transfer for security
- Node.js >= 18.x
- npm >= 9.x
- PM2 (for production)
- Flutter SDK >= 3.19.x
- Dart >= 3.3.x
- Android Studio / Xcode
- Android SDK >= 21 (Android 5.0+)
Copy backend/.env.example to backend/.env and fill in your values. Never commit the real .env (it is gitignored).
# PostgreSQL
DB_HOST=localhost
DB_PORT=5432
DB_NAME=qris_payments
DB_USER=qris_user
DB_PASSWORD=your_db_password
# Server
PORT=3000
# Escrow / wallets (generate fresh, never reuse or commit real values)
ESCROW_MASTER_MNEMONIC=your_twelve_to_twentyfour_word_mnemonic
DEPLOYER_PRIVATE_KEY=0x...
HOT_WALLET_PRIVATE_KEY=0x...
# Xendit (QRIS settlement)
XENDIT_API_KEY=xnd_development_...
# Lisk Sepolia
LISK_RPC_URL=https://rpc.sepolia-api.lisk.com
LISK_CHAIN_ID=4202
QRIS_ESCROW_V2_ADDRESS=0xda7c9CF0988547d6F88899A3a822630bAD52060d
LSK_TOKEN_ADDRESS=0x4270A0c8676A10ab8CbE3e92bFd187D94C8f248e# Navigate to backend directory
cd backend
# Install dependencies
npm install
# Start Postgres (Docker) + compile TS + run server
npm run start # docker-compose up + tsc + node lib/server.js
# Or development watch mode
npm run dev
# Production with PM2 (after `npm run build` compiles to lib/)
npm run build
pm2 start lib/server.js --name walt-backend
pm2 savecd backend
# Compile contracts
npx hardhat compile
# Deploy to Lisk Sepolia
npx hardhat run scripts/deploy.js --network liskSepolia
# Verify on Blockscout
npx hardhat verify --network liskSepolia <CONTRACT_ADDRESS># Navigate to mobile directory
cd mobile
# Get Flutter dependencies
flutter pub get
# Run on connected device/emulator
flutter run
# Build release APK
flutter build apk --release --split-per-abiUser WaltApp Backend WaltQRPayV3 Xendit Merchant
│ │ │ │ │ │
│ 1. Scan QRIS │ │ │ │ │
│───────────────────────>│ │ │ │ │
│ │ │ │ │ │
│ │ 2. Create Payment │ │ │ │
│ │──────────────────────>│ │ │ │
│ │ │ │ │ │
│ │ │ 3. Get LSK/IDR rate │ │ │
│ │ │ Calculate amount │ │ │
│ │ │ │ │ │
│ │<──────────────────────│ │ │ │
│ │ PaymentIntent │ │ │ │
│ │ │ │ │ │
│<───────────────────────│ │ │ │ │
│ Show: "Pay 2.5 LSK" │ │ │ │ │
│ │ │ │ │ │
│ 4. Confirm │ │ │ │ │
│───────────────────────>│ │ │ │ │
│ │ │ │ │ │
│ │ 5. approve() + pay() │ │ │ │
│ │───────────────────────────────────────────────>│ │ │
│ │ │ │ │ │
│ │ │ │ ESCROW LOCKED │ │
│ │ │ │ │ │
│ │ │<───────────────────────│ │ │
│ │ │ PaymentCreated │ │ │
│ │ │ │ │ │
│ │ │ 6. release() │ │ │
│ │ │───────────────────────>│ │ │
│ │ │ │ │ │
│ │ │ │ Transfer to │ │
│ │ │ │ FeeCollector │ │
│ │ │ │─────────────────────>│ │
│ │ │ │ │ │
│ │ │ 7. Create disbursement │ │ │
│ │ │─────────────────────────────────────────────>│ │
│ │ │ │ │ │
│ │ │ │ │ 8. Bank Transfer │
│ │ │ │ │───────────────────>│
│ │ │ │ │ │
│<───────────────────────│ │ │ │ │
│ Payment Success! │ │ │ │ │
- Creator creates bill with participants and deadline
- Participants pay their share to smart contract escrow
- When all paid → Creator can withdraw funds
- If deadline passed → Participants can claim refund
- User selects fromToken and toToken
- Backend calculates quote with real-time prices
- User approves token spend
- Smart contract executes swap with 0.2% fee
- User receives swapped tokens
walt-app/
├── backend/ # Node.js + TypeScript Backend
│ ├── contracts/ # Solidity Smart Contracts
│ │ ├── CanmaSplitBillV5.sol
│ │ ├── WaltQRPayV3.sol
│ │ └── WaltSwapV2.sol
│ ├── scripts/ # Deployment scripts (Hardhat)
│ ├── src/
│ │ ├── server.ts # Express server (main entry)
│ │ ├── services/ # QRIS, escrow, swap, faucet services
│ │ └── config/ # Lisk / Xendit config
│ ├── hardhat.config.cjs # Hardhat configuration
│ └── package.json
│
├── mobile/ # Flutter Mobile App
│ ├── lib/
│ │ ├── ui/ # UI Components & Pages
│ │ │ ├── pages/
│ │ │ │ ├── home_page.dart
│ │ │ │ ├── scan_qris_page.dart
│ │ │ │ ├── split_bill_page.dart
│ │ │ │ └── swap_page.dart
│ │ │ └── widgets/
│ │ ├── services/ # Backend & Blockchain Services
│ │ │ ├── qris_payment_service.dart
│ │ │ ├── canma_splitbill_v5_service.dart
│ │ │ └── wallet_service.dart
│ │ └── main.dart
│ ├── pubspec.yaml
│ └── android/
│
└── README.md
| Layer | Technology |
|---|---|
| Mobile | Flutter 3.19, Dart 3.3, web3dart, BLoC |
| Backend | Node.js 18, Express, ethers.js |
| Blockchain | Lisk Sepolia, Solidity 0.8.20, Hardhat |
| Auth | Web3Auth (non-custodial), Firebase Auth |
| Payment | Xendit xenPlatform (QRIS settlement) |
| Security | OpenZeppelin 5.x |
- OpenZeppelin 5.x battle-tested libraries
- ReentrancyGuard on all state-changing functions
- SafeERC20 for token transfers
- Pull-based refunds (prevents griefing)
- Role-based access control
- Web3Auth non-custodial key management
- Private keys stored only on user device
- PIN protection for transactions
- flutter_secure_storage (encrypted)
- HTTPS-only communication
MIT License - see LICENSE for details.
- Fork the repository
- Create feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open Pull Request
Built for Lisk Builders Challenge 2024
Made with ❤️ by Walt Team