README
Web3 Multi-Chain Wallet š°
A self-custodial multi-chain crypto wallet supporting 12 blockchain networks (8 EVM + Solana) built with Expo, React Native, ethers.js, and Solana Web3.js.
⨠Features
- š Self-Custodial - You control your private keys (non-custodial)
- š 12 Networks - Ethereum, Polygon, Linea, zkSync (mainnet + testnet) + Solana (mainnet + devnet + testnet)
- šø Multi-Token - Native tokens (ETH, POL, SOL) + USDC stablecoin across all chains
- š± Mobile-First - Native iOS & Android apps via Expo
- š Dark Mode - Automatic light/dark theme support
- š Secure Storage - OS-encrypted AsyncStorage for private keys
- š Transaction History - Track all transfers per network
- ā Fully Typed - TypeScript for blockchain interactions
šø Screenshots
<div align="center"> <img src="screenshots/screenshot_1.png" alt="Welcome Screen" width="200" /> <img src="screenshots/screenshot_2.png" alt="Create Wallet" width="200" /> <img src="screenshots/screenshot_3.png" alt="Import Wallet" width="200" /> <img src="screenshots/screenshot_4.png" alt="Wallet Balance" width="200" /> </div> <div align="center"> <img src="screenshots/screenshot_5.png" alt="Send Transfer" width="200" /> <img src="screenshots/screenshot_6.png" alt="Transaction History" width="200" /> <img src="screenshots/screenshot_7.png" alt="Settings" width="200" /> <img src="screenshots/screenshot_8.png" alt="Dark Mode" width="200" /> </div>šļø Tech Stack
- Framework: Expo SDK 54 + React Native 0.75.5
- EVM Library: ethers.js v6.13.5 (Ethereum, Polygon, Linea, zkSync)
- Solana Library: @solana/web3.js + @solana/spl-token (SOL & SPL tokens)
- Networks: 8 EVM chains + 3 Solana networks (mainnet + testnet variants)
- RPC Provider: Infura (EVM) + Public RPCs (Solana)
- UI: NativeWind v4 + Tailwind CSS
- Navigation: Expo Router (file-based routing)
- Language: TypeScript 5.x
- Storage: AsyncStorage (OS-encrypted)
š Supported Networks
| Network | Type | Status | Native Token |
|---|---|---|---|
| Ethereum Mainnet | EVM | Mainnet | ETH |
| Ethereum Sepolia | EVM | Testnet | ETH |
| Polygon Mainnet | EVM | Mainnet | POL |
| Polygon Amoy | EVM | Testnet | POL |
| Linea Mainnet | EVM | Mainnet | ETH |
| Linea Sepolia | EVM | Testnet | ETH |
| zkSync Mainnet | EVM | Mainnet | ETH |
| zkSync Sepolia | EVM | Testnet | ETH |
| Solana Mainnet | Non-EVM | Mainnet | SOL |
| Solana Devnet | Non-EVM | Testnet | SOL |
| Solana Testnet | Non-EVM | Testnet | SOL |
USDC Support: Available on all networks with proper SPL mint addresses for Solana.
š Quick Start
Prerequisites
- Node.js 18+ and npm/yarn
- Expo CLI (optional, can use npx)
- iOS Simulator (macOS) or Android Emulator
- (Solana) Solana CLI optional for airdrop testing
Installation
-
Install dependencies
npm install -
Configure environment variables
# Copy template cp .env.example .env # Add your Infura API key (get free key at https://infura.io) INFURA_API_KEY=your_key_here -
Start development server
npm start -
Run on device/emulator
# iOS (macOS only) npm run ios # Android npm run android # Web (limited blockchain features) npm run web
š Documentation
- ARCHITECTURE.md - System design, data flow, component hierarchy
- SOLANA_GUIDE.md - Solana devnet setup, testing, troubleshooting
- ENV_SETUP.md - How to obtain and fill .env values (Infura, explorers, RPCs)
š± App Structure
Main Screens
App Launch
āāā No account ā auth/ (authentication)
ā āāā Create new account (BIP39 seed phrase)
ā āāā Import existing account (seed phrase or private key)
ā
āāā Account exists ā (tabs)/ (main app)
āāā wallet/ (home screen)
ā āāā Balance display (native token + USDC)
ā āāā Quick actions (Send, Receive)
ā āāā Chain selector (11 networks)
ā
āāā transactions/ (history)
ā āāā Transaction list (Etherscan/SolanaExplorer API)
ā
āāā settings/
āāā Network selection
āāā Account details
āāā Profile management
ā āāā Welcome Screen (Create/Import wallet) ā āāā Recovery Input (Enter seed phrase) āāā Has account ā (tabs)/ (main app) āāā Wallet Tab (Balance, Transfer) āāā Transactions Tab (History) āāā Settings Tab (App info, Version)
### Key Features
#### 1. Create New Wallet
- Generates BIP39 12-word seed phrase
- Derives account using BIP44 standard (EVM compatible)
- Stores encrypted in AsyncStorage (OS-managed encryption)
- Generates 12-word recovery phrase
- Returns account with address, private key, and balance
#### 2. Import Existing Wallet
- **Via Seed Phrase**: Recover 12-24 word BIP39 mnemonic
- **Via Private Key**: Import 0x-prefixed hex or Solana base58 secret key
- Derives same address as original wallet
- Syncs balance from blockchain
#### 3. View & Manage Balance
- Real-time balance display (native token + USDC)
- Refresh via pull-to-refresh
- Copy address to clipboard
- View on chain-specific block explorer
- Multi-chain selection (11 networks)
#### 4. Send Transfers
- **EVM**: Send native ETH/MATIC/POL + USDC (ERC-20)
- **Solana**: Send SOL + USDC (SPL token)
- Automatic address validation per chain
- Real-time transaction status
- Block explorer link in success message
#### 5. Transaction History
- List recent transfers (fetched from Etherscan API)
- Transaction details (hash, to/from, amount, status)
- One-tap block explorer access
- Per-chain history (if API key configured)
#### 6. Settings
- App version display (from package.json)
- Per-chain network information
- Account address with copy button
- Links to documentation
- Security & privacy information
## š Security & Key Management
ā ļø **CRITICAL - Read Before Using with Real Funds:**
- **Never share seed phrase or private key** with anyone (including support)
- **Always verify recipient addresses** (copy-paste, never type)
- **Non-custodial**: Only you have access to your private keys
- **Irreversible transfers**: Blockchain transactions cannot be undone
- **Device-only storage**: Keys never leave your phone
- This wallet is **testnet-ready** ā fully audit before mainnet use
### Private Key Security
ā
**Secure:**
- Stored in AsyncStorage with OS-level encryption
- Never transmitted over network
- Only decrypted in memory when needed
- Device PIN/biometric protects local storage
ā **Not Secure:**
- Logging private keys to console
- Storing in plain text in app files
- Sharing screenshots with keys visible
- Using in public WiFi without VPN
### Testing Safely
- **Use testnets only** until confident (Sepolia, Amoy, Devnet)
- **Start with small amounts** ($1-5 test tokens)
- **Verify one transfer** before bulk operations
- **Test recovery** by importing seed phrase into fresh app
- **Save seed phrase** in secure location (password manager, not photos)
## š Getting Test Tokens
### EVM Testnets
| Network | Test Token | Faucet |
|---------|-----------|--------|
| Ethereum Sepolia | Sepolia ETH | [QuickNode](https://faucet.quicknode.com/drip) |
| Polygon Amoy | Amoy POL | [Polygon Faucet](https://faucet.polygon.technology) |
| Linea Sepolia | Linea ETH | [Linea Faucet](https://faucet.linea.build) |
| zkSync Sepolia | zkSync ETH | [zkSync Faucet](https://sepolia.era.zk/faucet) |
### Solana Testnet
```bash
# Devnet (recommended for testing)
solana airdrop 2 <wallet_address> --url devnet
# Or web faucet: https://solfaucet.com
# Select "Devnet" and paste wallet address
š Project Structure
src/
āāā config/
ā āāā index.ts # RPC URLs, API keys, env fallbacks
āāā interfaces/
ā āāā Account.ts # Account type
ā āāā Chain.ts # Chain configuration + registry
ā āāā Token.ts # Token definitions + USDC mints
āāā context/
ā āāā AccountContext.tsx # Global account & chain state
ā āāā ThemeContext.tsx # Dark mode theme
āāā wallet-utils/
ā āāā AccountUtils.ts # Account generation, balance (EVM)
ā āāā SolanaUtils.ts # Balance & transfers (Solana)
ā āāā TokenUtils.ts # ERC-20 token transfers + metadata
ā āāā TransactionUtils.ts # Native token transfers + history
āāā hooks/
ā āāā use-color-scheme.ts # Dark/light mode detection
ā āāā use-theme-color.ts # Theme color getter
āāā components/
ā āāā ui/ # Generic UI components
ā āāā AccountCreate.tsx # New account generation
ā āāā AccountDetails.tsx # Account info display
ā āāā TransactionDetails.tsx # Transaction inspector
āāā constants/
āāā theme.ts # Color constants
app/
āāā _layout.tsx # Root layout (auth check)
āāā auth/
ā āāā index.tsx # Login/signup screen
āāā (tabs)/
āāā _layout.tsx # Tab navigation
āāā wallet.tsx # Main wallet (balance, send, receive)
āāā transactions.tsx # Transaction history
āāā settings/
āāā index.tsx # Settings & profile
Key Design Patterns:
@/alias =src/(TypeScript path)wallet-utils/= blockchain-specific functions (no React)- Wallet UI = pure React components with state management
- Multi-chain detection via
chain.isNonEVMflag
š ļø Development & Testing
Build & Run
# Development with hot reload
npm start
npm run android # Android emulator
npm run ios # iOS simulator
# Production build
npm run android:release
npm run ios:release
Code Quality
npm run typecheck # TypeScript compilation check
npm run lint # ESLint code quality check
npm test # Jest unit tests (if configured)
Debugging
Console Logs:
// In wallet.tsx or utils
console.log('Chain:', selectedChain);
console.log('Balance:', balance);
console.log('TX Hash:', transactionHash);
Block Explorers:
- Ethereum/Polygon: https://sepolia.etherscan.io (use
?address=0x...or?tx=0x...) - Solana: https://explorer.solana.com (append
?cluster=devnetfor devnet)
Network Errors:
- Check RPC endpoint is reachable
- Verify API key in
.envis correct - Try alternative public RPC if Infura fails
š Troubleshooting
Common Issues
"Insufficient balance" error:
- Ensure you requested test tokens from faucet
- Wait 1-2 minutes for tokens to arrive
- Refresh balance in app (pull-to-refresh)
"Invalid address" error:
- Copy-paste address (don't type manually)
- Ensure address is for current selected network
- For Solana: address starts with number (e.g.,
9sFJ...), not0x - For EVM: address starts with
0x
"Transaction timeout" error:
- Network congestion - retry in a few minutes
- Check RPC endpoint status
- Increase transaction fee (if supported)
"Private key not working":
- Ensure 0x prefix for EVM keys (hex format)
- For Solana: key should be base58 secret key, not base64
- Try importing via seed phrase instead
App crashes on startup:
# Clear Expo cache
rm -rf node_modules/.expo
npm install
# Clear app data
npm start -- --clear
"Chain not supported" when switching networks:
- Ensure all chains are defined in src/interfaces/Chain.ts
- Check
src/config/index.tshas RPC URLs for chain - Verify
.envhas any required API keys
Solana transfers failing:
- Ensure recipient address is valid Solana public key (base58)
- Check account has SOL for fees (min ~0.000005 SOL)
- For USDC: recipient must exist or use SPL associated token account
- See SOLANA_GUIDE.md for detailed Solana troubleshooting rm -rf node_modules npm install npx expo start --clear
**Wallet not loading:**
- Check internet connection
- Verify RPC endpoint in `app/_config/index.ts`
- Check AsyncStorage permissions
**Transaction fails:**
- Ensure address is valid (0x...)
- Ensure sufficient balance
- Verify network connectivity
**Route warnings:**
- Utility directories use underscore prefix (\_config,\_context, etc.)
- These won't be treated as routes by Expo Router
**Watchman recrawl warning:**
```bash
watchman watch-del '/Users/.../crypto-wallet'
watchman watch-project '/Users/.../crypto-wallet'
š Useful Links
- Polygon: https://polygon.technology
- Polygonscan: https://amoy.polygonscan.com
- Expo Docs: https://docs.expo.dev
- ethers.js: https://docs.ethers.org/v6/
- React Native: https://reactnative.dev
š Version History
- v1.0.0 - Initial release
- Self-custodial wallet with BIP39/BIP44
- Create/Import accounts
- POL transfers on Polygon Amoy
- Transaction history
- Dark mode support
- Settings screen with app info
š License
This project is open source and available under the MIT License.
Built with ā¤ļø using Expo and React Native