From fc3f0e00c8272121b105459ba6fc3f0d7de99d0c Mon Sep 17 00:00:00 2001 From: sneak Date: Wed, 25 Feb 2026 18:04:28 +0700 Subject: [PATCH] Rewrite TODO as 0.1.0 MVP checklist, add screen map Full screen map with iOS-style stack navigation: Welcome, Home, AddWallet, ImportKey, AddressDetail, Send, Receive, AddToken, Settings, Approval. Each screen documents its elements and transitions. TODO reorganized into Done, Wallet Management, Sending, Receiving, Display, Tokens, Testing, and Post-MVP. External Services updated to include CoinDesk price API. --- README.md | 275 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 225 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 0b92f75..4f926a0 100644 --- a/README.md +++ b/README.md @@ -147,34 +147,151 @@ send/receive). Navigation is flat — every view has a "Back" or "Cancel" button that returns to the previous context. No deep nesting, no tabs, no hamburger menus. -### UI Views +### Screen Map -The popup has the following views, switched via simple show/hide: +Navigation uses a stack model (like iOS): each action pushes a screen onto the +stack, and "Back" pops it. The root screen is either Welcome (no wallets) or +Home (has wallets). Screens are listed below with their elements and +transitions. -1. **Welcome**: Shown on first use. Single "Add wallet" button. -2. **Add wallet**: A unified view for both creating and importing recovery - phrase wallets. The recovery phrase text area starts empty. A clickable die - button `[die]` generates a random 12-word phrase and fills it in. If the user - already has a phrase, they paste it directly. When the die is clicked, a - warning box appears reminding the user to write the phrase down. No password - required — the xpub is derived and stored for read-only access. -3. **Import private key**: Paste a private key. This creates a wallet with a - single address. -4. **Main**: All wallets listed, each showing its addresses (full, untruncated) - and ETH balance. "+" next to recovery phrase wallets to add another address. - "+ Add wallet" at the bottom. Settings button in the header. Future: a - sub-heading showing total portfolio value in USD (and eventually other - currencies). -5. **Address detail**: Full address (click to copy), ETH balance, USD value - (future), Send/Receive buttons, token list with "+ Add" button. -6. **Send**: Token selector, recipient address, amount. Cancel returns to - address detail. -7. **Receive**: Full address displayed with "Copy address" button. -8. **Add token**: Enter contract address. The extension looks up the token - name/symbol automatically. -9. **Settings**: Network (RPC endpoint URL) with explanatory text. -10. **Approval**: When a website requests wallet access or a signature, shows - the site origin, request details, and Allow/Deny buttons. +#### Welcome + +- **When**: No wallets exist yet. +- **Elements**: "AutistMask" heading, brief intro text, "Add wallet" button. +- **Transitions**: + - "Add wallet" → pushes **AddWallet** + +#### Home + +- **When**: At least one wallet exists. This is the root screen. +- **Elements**: + - Header: "AutistMask", Settings button + - Total ETH balance across all addresses (large text) + - Total USD value (small text below ETH total, cached 5 min) + - List of wallets, each showing: + - Wallet name (editable — tap to rename) + - "+" button (HD wallets only) to derive next address + - List of addresses under that wallet: + - Address name (editable — tap to rename, default "Address N") + - Full address (untruncated) + - ETH balance + USD value (small text) + - "+ Add wallet" button at the bottom +- **Transitions**: + - Tap address → pushes **AddressDetail** + - "+" on wallet → derives address inline (no screen change) + - "+ Add wallet" → pushes **AddWallet** + - Settings → pushes **Settings** + +#### AddWallet + +- **When**: User wants to add a new wallet (from Home or Welcome). +- **Elements**: + - "Add Wallet" heading + - Instruction text + - Die button `[die]` (generates random recovery phrase, can be clicked + repeatedly) + - Recovery phrase textarea (empty by default, or filled by die) + - Backup warning box (shown after die is clicked) + - "Add" button, "Back" button + - "Have a private key instead?" link → pushes **ImportKey** +- **Transitions**: + - "Add" (valid phrase) → pops to **Home** + - "Back" → pops to previous (Home or Welcome) + - "Have a private key instead?" → pushes **ImportKey** + +#### ImportKey + +- **When**: User wants to import a single private key. +- **Elements**: + - "Import Private Key" heading + - Instruction text + - Private key input (password-masked) + - "Import" button, "Back" button +- **Transitions**: + - "Import" (valid key) → pops to **Home** + - "Back" → pops to previous + +#### AddressDetail + +- **When**: User tapped an address from Home. +- **Elements**: + - Header: wallet name, "Back" button + - Address name (editable — tap to rename) + - ENS name (if resolved, shown above address) + - Full address (tap to copy, "Copied!" feedback) + - ETH balance (large) + USD value (small) + - "Send" button, "Receive" button + - Token list with balances + - "+ Add" token button +- **Transitions**: + - "Send" → pushes **Send** + - "Receive" → pushes **Receive** + - "+ Add" → pushes **AddToken** + - "Back" → pops to **Home** + +#### Send + +- **When**: User wants to send ETH or a token from this address. +- **Elements**: + - "Send" heading + - Token selector (ETH + any added tokens) + - "To" input (accepts address or ENS name, resolves before sending) + - Amount input + - Fee estimate (shown after entering amount) + - "Send" button, "Cancel" button + - Status area (resolving ENS, confirming, errors) +- **Transitions**: + - "Send" (valid) → prompts for password (to decrypt private key), submits + transaction, shows result, stays on screen + - "Cancel" → pops to **AddressDetail** + +#### Receive + +- **When**: User wants to receive funds at this address. +- **Elements**: + - "Receive" heading + - Instruction text + - QR code encoding the address + - Full address (displayed, selectable) + - "Copy address" button + - "Back" button +- **Transitions**: + - "Back" → pops to **AddressDetail** + +#### AddToken + +- **When**: User wants to track an ERC-20 token on this address. +- **Elements**: + - "Add Token" heading + - Instruction text (find contract address on Etherscan) + - Contract address input + - Token info preview (name, symbol — fetched from contract) + - "Add" button, "Cancel" button +- **Transitions**: + - "Add" (valid contract) → pops to **AddressDetail** + - "Cancel" → pops to **AddressDetail** + +#### Settings + +- **When**: User tapped Settings from Home. +- **Elements**: + - "Settings" heading + - Network section: RPC endpoint URL input, "Save" button, explanatory text + - "Back" button +- **Transitions**: + - "Back" → pops to **Home** + +#### Approval (future) + +- **When**: A connected website requests wallet access or a transaction + signature. Opened by the background script, not by user navigation. +- **Elements**: + - "A website is requesting access" heading + - Site origin (bold) + - Request type and details (preformatted) + - "Allow" button, "Deny" button +- **Transitions**: + - "Allow" / "Deny" → closes popup (returns result to background script) ### External Services @@ -189,17 +306,22 @@ communicates with external services to function as a wallet: any endpoint they prefer, including a local node). This is the only external service the extension talks to. +- **CoinDesk CADLI price API**: Used to fetch ETH/USD and token/USD prices for + displaying fiat values. The price is cached for 5 minutes to avoid excessive + requests. No API key required. No user data is sent — only a list of token + symbols. + What the extension does NOT do: - No analytics or telemetry services - No token list APIs (user adds tokens manually by contract address) -- No price feed APIs (balances are shown in token units, not fiat) - No phishing/blocklist APIs - No Infura/Alchemy dependency (any JSON-RPC endpoint works) - No backend servers operated by the developer -The user's RPC endpoint is the single point of external communication. Users who -want maximum privacy can point it at their own Ethereum node. +The user's RPC endpoint and the CoinDesk price API are the only external +services. Users who want maximum privacy can point the RPC at their own node +(price fetching can be disabled in a future version). ### Dependencies @@ -318,28 +440,81 @@ project owner. - Browser notifications - Transaction history (use Etherscan) -## TODO +## TODO — 0.1.0 MVP -- [x] Project scaffolding (Makefile, Dockerfile, CI, manifests) -- [x] Set up Tailwind CSS build pipeline -- [x] Build popup UI views (all 13 views with stub state) -- [ ] Implement BIP-39 mnemonic generation and validation -- [ ] Implement BIP-32/BIP-44 HD key derivation for Ethereum -- [ ] Implement private key import and address derivation -- [ ] Implement encrypted storage for wallet data -- [ ] Implement background wallet manager -- [ ] Implement EIP-1193 provider and content script injection -- [ ] Implement ETH balance lookup via RPC -- [ ] Implement ETH send (transaction construction + signing) -- [ ] Implement ERC-20 token management (add by contract, view balance, send) -- [ ] Implement site connection approval flow -- [ ] Implement transaction signing approval flow -- [ ] Implement message signing (`personal_sign`, `eth_sign`) -- [ ] Add USD value display (price feed TBD) -- [ ] Add multi-currency fiat display support -- [ ] Test on Chrome and Firefox -- [ ] Write tests for crypto operations -- [ ] Write tests for transaction construction +Everything needed for a minimal working wallet that can send and receive ETH. + +### Done + +- [x] Project scaffolding (Makefile, Dockerfile, CI, manifests, esbuild) +- [x] Tailwind CSS build pipeline +- [x] Popup UI shell with screen stacking (Welcome, AddWallet, Home, + AddressDetail, Send, Receive, Settings) +- [x] BIP-39 mnemonic generation via ethers.js (die button) +- [x] BIP-39 mnemonic validation on import +- [x] BIP-32/BIP-44 HD key derivation (real addresses from xpub) +- [x] Private key import (real address via ethers.Wallet) +- [x] Xpub stored unencrypted for read-only address derivation +- [x] State persistence to extension storage (survives popup close) +- [x] Live ETH balance fetching via JSON-RPC (`eth_getBalance`) +- [x] ENS reverse lookup (address → name) and forward resolution (name → address + in Send field) +- [x] ETH/USD price fetching via CoinDesk API +- [x] USD value display next to ETH balances +- [x] Full address display everywhere (no truncation) +- [x] Token list module with ~150 ERC-20 tokens ordered by market cap + +### Wallet Management + +- [ ] Rename wallets (tap wallet name on Home to edit) +- [ ] Rename addresses (tap address name on AddressDetail to edit) +- [ ] Delete wallet (with confirmation) +- [ ] Delete address from HD wallet (with confirmation) +- [ ] Show wallet's recovery phrase (requires password, from Settings or wallet + context menu) + +### Sending + +- [ ] Encrypt recovery phrase / private key with password via libsodium + (Argon2id + XSalsa20-Poly1305) +- [ ] Password prompt on Send (decrypt private key to construct transaction) +- [ ] Transaction construction via ethers.js (to, value, gasLimit, gasPrice) +- [ ] Gas estimation and fee display before confirming +- [ ] Broadcast transaction via `eth_sendRawTransaction` +- [ ] Transaction status feedback (pending → confirmed / failed) + +### Receiving + +- [ ] QR code generation for address (text-based or lightweight QR library) + +### Display + +- [ ] Home screen: total ETH balance summed across all addresses +- [ ] Home screen: total USD value (small text under total ETH) +- [ ] Cache ETH/USD price for 5 minutes (don't re-fetch on every popup open) +- [ ] Per-address USD value in small text under ETH balance everywhere + +### Tokens (ERC-20) + +- [ ] Add token by contract address (fetch name/symbol/decimals from contract) +- [ ] Display ERC-20 token balances per address +- [ ] Send ERC-20 tokens + +### Testing + +- [ ] Tests for mnemonic generation and address derivation +- [ ] Tests for xpub derivation and child address generation +- [ ] Tests for token list module (getTopTokenPrices, getTopTokenSymbols) +- [ ] Test on Chrome (Manifest V3) +- [ ] Test on Firefox (Manifest V2) + +### Post-MVP + +- [ ] EIP-1193 provider injection (window.ethereum) for web3 site connectivity +- [ ] Site connection approval flow +- [ ] Transaction signing approval flow (requests from connected sites) +- [ ] Message signing (`personal_sign`, `eth_sign`) +- [ ] Multi-currency fiat display (EUR, GBP, etc.) - [ ] Security audit of key management ## License