Cross-chain crypto payments for Android — scan a QR, pick your chain, pay in any token. The receiver gets USDC on their preferred chain. Powered by the Flash Protocol backend which aggregates quotes from 6 cross-chain providers across 70+ blockchain networks.
- QR Payments — Every user has a QR code. Scan it, enter an amount, pay from any chain.
- Payment Links — Create a link with a fixed amount, share it anywhere.
- 70+ Chains — Pay from any supported chain; receives settle in USDC.
- Multi-Wallet — Connect EVM wallets (MetaMask, Trust, Rainbow, Coinbase) and Solana wallets via Reown AppKit.
- Best-Price Routing — Aggregates quotes from 6 providers, picks the cheapest route automatically.
- Dark Mode — System/Light/Dark with persistent preference.
- Onboarding — First-launch walkthrough.
- Deep Linking —
flashpay://custom scheme +https://flash-protocol.vercel.app/pay/universal links.
Payments are supported across 70+ blockchain networks via the Flash Protocol backend:
- EVM: Ethereum, Arbitrum, Optimism, Base, Polygon, BSC, Avalanche, Linea, Scroll, zkSync Era, and more.
- Non-EVM: Solana, Cosmos (via IBC), Tron, TON, Starknet.
- Bitcoin: Bitcoin, Litecoin.
Quotes are aggregated from 6 cross-chain providers:
| Provider | Type |
|---|---|
| LI.FI | Aggregator |
| Rango Exchange | Aggregator |
| Rubic | Aggregator |
| Symbiosis | Liquidity Protocol |
| Circle CCTP | Bridge Protocol |
| NEAR Intents | Intent Network |
| Layer | Technology |
|---|---|
| Framework | Expo SDK 54, Expo Router v6 (file-based routing) |
| Runtime | React Native 0.81, React 19 |
| Wallet | Reown AppKit v2 + Wagmi v3 + Viem v2 (EVM), Solana adapter |
| Styling | NativeWind v4 (Tailwind CSS for RN), Tailwind v3 |
| Typography | Inter via @expo-google-fonts/inter |
| State | Zustand v5 (client), TanStack React Query v5 (server) |
| HTTP | Axios v1 with x-wallet-address header interceptor |
| QR | react-native-qrcode-svg (generation), expo-camera (scanning) |
| Animations | react-native-reanimated v4: Layout animations, gesture-driven bottom sheets |
| Testing | Jest v30, ts-jest v29 |
| Language | TypeScript 5.9, React Compiler enabled |
- Node.js ≥ 18
- npm (package manager)
- Android Studio with Android SDK (API 24+)
- Java 17+ (for Gradle)
- A physical Android device or emulator
git clone git@github.com:HoomanBuilds/flash-protocol-android.git
cd flash-protocol-android
npm installCreate .env.local in the project root:
EXPO_PUBLIC_REOWN_PROJECT_ID=your_reown_project_idGet a project ID from Reown Cloud.
# Build native code + start Metro bundler
npx expo run:androidNote: This project uses a development build, not Expo Go. The first run compiles the native Android project (~2-3 min). Subsequent runs are faster.
npm test # Run tests (Jest)
npx expo lint # Run ESLint
npx tsc --noEmit # Type checkapp/ # Expo Router screens
├── _layout.tsx # Root: WagmiProvider > QueryClient > AppKit > Stack
├── onboarding.tsx # First-launch walkthrough
├── payment.tsx # Payment flow (chain/token select → quotes → execute)
├── create-link.tsx # Create payment link
├── transaction-status.tsx # Tx polling + success/failure UI
└── (tabs)/
├── _layout.tsx # Bottom tab bar (Home, Scan, Receive, Activity, Settings)
├── index.tsx # Home — wallet status, recent txs, feature carousel
├── send.tsx # QR scanner (expo-camera)
├── receive.tsx # QR code display + share
├── activity.tsx # Transaction history feed
└── settings.tsx # Receive chain prefs, theme, wallet info
config/
├── appkit.ts # Reown AppKit setup (EVM + Solana adapters, network discovery)
└── reown.ts # Project ID + app metadata
services/api/
├── client.ts # Axios instance (base: flash-protocol.vercel.app, 30s timeout)
├── chains.ts # getChains(), getTokens()
├── quotes.ts # getQuotes()
├── transactions.ts # initiateTransaction(), submitHash(), getReceipt(), getHistory()
├── profile.ts # getProfile(), updateProfile(), getReceiverProfile()
├── paymentLinks.ts # getPaymentLink(), createPaymentLink(), listPaymentLinks()
└── price.ts # getPrice()
hooks/
├── useChains.ts # Fetch chains with optional hasUSDC/type filters + sorting
├── useTokens.ts # Fetch tokens for a specific chain
├── useQuotes.ts # Fetch cross-chain quotes with 30s polling
├── useTransaction.ts # Full tx lifecycle: initiate → submit hash → poll receipt
├── useProfile.ts # Fetch/update user profile, syncs to Zustand
├── useUSDCToken.ts # Resolve USDC token address for a chain
├── use-dark.ts # Dark mode hook
├── use-theme-color.ts # Theme-aware color resolution
├── use-color-scheme.ts # System color scheme detection
└── use-color-scheme.web.ts # Web-specific color scheme
stores/
├── wallet.ts # address, isConnected
├── payment.ts # Full payment flow state
├── profile.ts # User profile cache
└── theme.ts # Theme mode, persisted to AsyncStorage
components/
├── payment/
│ ├── chain-selector.tsx # Searchable chain picker (grouped by type, popular pinned)
│ └── token-selector.tsx # Token picker for selected chain
└── ui/
├── bottom-sheet.tsx # Gesture-driven bottom sheet (Reanimated + GestureHandler)
├── pressable-scale.tsx # Pressable with scale animation + optional haptics
├── toast.tsx # Toast notification system
├── skeleton.tsx # Shimmer loading placeholders
├── icon-symbol.tsx # SF Symbols → Material Icons mapping
├── illustrations.tsx # Inline SVG empty-state illustrations
├── onboarding-illustrations.tsx
├── network-banner.tsx # Offline/connectivity banner
└── collapsible.tsx # Expandable sections
lib/
├── address.ts # Wallet address validation + formatting
├── amount.ts # Token amount conversion (human ↔ raw units)
├── clipboard.ts # Copy-to-clipboard utility
└── solana.ts # Solana-specific helpers
utils/
└── linking.ts # Deep link parser (flashpay:// + universal links)
constants/
├── theme.ts # Color palette, semantic colors
└── usdc.ts # USDC contract addresses per chain
types/
└── api.ts # TypeScript interfaces (Chain, Token, Quote, Transaction, etc.)
__tests__/
├── address-validation.test.ts
├── amount.test.ts
├── deep-link.test.ts
└── stores.test.ts
flowchart TD
A["Scan QR / Open Payment Link"] --> B{"Payment Link or P2P?"}
B -->|"Payment Link"| C["Fetch link details (amount, chain, wallet)"]
B -->|"P2P (QR Scan)"| D["Fetch receiver profile (preferred chain/token)"]
C --> E["Select Pay-From Chain & Token"]
D --> E
E --> F["Fetch Quotes (POST /api/quotes)"]
F --> G["Initiate Transaction (POST /api/transactions/initiate)"]
G --> H["Execute via Wallet (wagmi useSendTransaction)"]
H --> I["Submit Tx Hash (PATCH /api/transactions/id/hash)"]
I --> J["Poll Receipt every 5s (GET /api/transactions/id/receipt)"]
J --> K{"Status?"}
K -->|"Completed"| L["✅ Success Screen"]
K -->|"Failed"| M["❌ Failure Screen"]
K -->|"Pending"| J
All API calls go through https://flash-protocol.vercel.app.
Authentication: No sessions or JWT — wallet address is sent via x-wallet-address header, auto-injected by the Axios interceptor.
| Method | Endpoint | Auth | Description |
|---|---|---|---|
GET |
/api/chains |
No | Supported chains (?hasUSDC=true to filter) |
GET |
/api/tokens?chainKey=X |
No | Tokens on a chain |
GET |
/api/price?chainId=X&tokenAddress=X&symbol=X |
No | Token USD price |
POST |
/api/quotes |
No | Cross-chain quotes |
POST |
/api/transactions/initiate |
No | Log payment intent |
PATCH |
/api/transactions/{id}/hash |
No | Submit signed tx hash |
GET |
/api/transactions/{id}/receipt |
No | Poll tx status |
GET |
/api/payment-links/{id} |
No | Payment link details |
GET |
/api/profile/me |
Yes | User's receive preferences |
PUT |
/api/profile/me |
Yes | Update receive chain/token |
GET |
/api/profile/{wallet} |
Yes | Lookup another user's prefs |
GET |
/api/transactions/history |
Yes | Sent + received tx feed |
GET |
/api/payment-links |
Yes | User's payment links |
POST |
/api/payment-links |
Yes | Create payment link |
| Scheme | Example | Action |
|---|---|---|
| Custom | flashpay://pay/{linkId} |
Open payment for a link |
| Custom | flashpay://send?address={wallet} |
Open P2P payment to address |
| Universal | https://flash-protocol.vercel.app/pay/{linkId} |
Open payment for a link (Android App Link) |
- B&W aesthetic — Black, white, and gray palette only. No Material Design components.
- Square corners — No border radius on cards, buttons, or inputs.
- Inter font — Regular (400), SemiBold (600), Bold (700).
- Dark mode — Full support via NativeWind
dark:classes. Theme persisted to AsyncStorage. - Animations — Layout enter/exit via Reanimated, scale feedback on pressables, shimmer loading.
MIT
