Rewrite TODO as 0.1.0 MVP checklist, add screen map
All checks were successful
check / check (push) Successful in 5s

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.
This commit is contained in:
2026-02-25 18:04:28 +07:00
parent 097f90d7f8
commit fc3f0e00c8

275
README.md
View File

@@ -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