All checks were successful
check / check (push) Successful in 13s
Replace jargon-heavy terminal-style UI with plain-language views. New data model: wallets (HD or private key) contain addresses. Main view lists all addresses grouped by wallet with balances. HD wallets get a "+" to add addresses; key wallets have one. Two import paths: recovery phrase and private key. All labels use plain English, full-sentence errors, inline help text. README updated with full UI philosophy, language guide, data model, and navigation docs.
281 lines
12 KiB
Markdown
281 lines
12 KiB
Markdown
# AutistMask
|
|
|
|
AutistMask is a GPL-licensed JavaScript browser extension by
|
|
[@sneak](https://sneak.berlin) that provides a minimal Ethereum wallet for
|
|
Chrome and Firefox. It manages HD wallets derived from BIP-39 seed phrases and
|
|
supports sending and receiving ETH and ERC-20 tokens, as well as web3 site
|
|
connection and authentication via the EIP-1193 provider API.
|
|
|
|
## Getting Started
|
|
|
|
```bash
|
|
git clone https://git.eeqj.de/sneak/autistmask.git
|
|
cd autistmask
|
|
make install
|
|
make build
|
|
```
|
|
|
|
Load the extension:
|
|
|
|
- **Chrome**: Navigate to `chrome://extensions/`, enable "Developer mode", click
|
|
"Load unpacked", and select the `dist/chrome/` directory.
|
|
- **Firefox**: Navigate to `about:debugging#/runtime/this-firefox`, click "Load
|
|
Temporary Add-on", and select `dist/firefox/manifest.json`.
|
|
|
|
## Rationale
|
|
|
|
MetaMask has become bloated with swap UIs, portfolio dashboards, analytics,
|
|
tracking, and advertisements. It is no longer a simple wallet. Most alternatives
|
|
(Rabby, Rainbow, etc.) only support Chromium browsers, leaving Firefox users
|
|
without a usable option.
|
|
|
|
AutistMask exists to provide the absolute minimum viable Ethereum wallet
|
|
experience: manage seed phrases, derive HD addresses, send and receive ETH and
|
|
ERC-20 tokens, and connect to web3 sites. Nothing else. No swaps (that's what
|
|
the web is for), no analytics, no tracking, no ads, no portfolio views, no NFT
|
|
galleries. Just a wallet.
|
|
|
|
## Design
|
|
|
|
AutistMask is a browser extension targeting both Chrome (Manifest V3) and
|
|
Firefox (Manifest V2/V3 as supported). The codebase is shared between both
|
|
targets with platform-specific manifest files and a build step that produces
|
|
separate output directories.
|
|
|
|
### Architecture
|
|
|
|
```
|
|
src/
|
|
background/ — service worker / background script
|
|
index.js — extension lifecycle, message routing
|
|
wallet.js — wallet management (create, import, derive)
|
|
provider.js — EIP-1193 JSON-RPC provider implementation
|
|
transaction.js — transaction construction and signing
|
|
popup/ — popup UI (the main wallet interface)
|
|
index.html
|
|
index.js
|
|
components/ — UI components (account list, send form, etc.)
|
|
styles/ — CSS (Tailwind)
|
|
content/ — content script injected into web pages
|
|
index.js — injects the provider into page context
|
|
inpage.js — the window.ethereum provider object
|
|
shared/ — shared utilities
|
|
crypto.js — BIP-39 mnemonic, HD key derivation, signing
|
|
storage.js — encrypted storage abstraction
|
|
constants.js — chain IDs, default RPC endpoints, ERC-20 ABI
|
|
rpc.js — JSON-RPC client for Ethereum nodes
|
|
manifest/
|
|
chrome.json — Manifest V3 for Chrome
|
|
firefox.json — Manifest V2/V3 for Firefox
|
|
```
|
|
|
|
### UI Design Philosophy
|
|
|
|
The UI follows a "Universal Paperclips" aesthetic — a deliberately spartan,
|
|
almost brutalist approach. The guiding principle is that an unskilled,
|
|
non-technical person should be able to figure out how to use it without any
|
|
crypto knowledge.
|
|
|
|
#### Visual Style
|
|
|
|
- **Monochrome**: Black text on white background. No brand colors, no gradients,
|
|
no color-coding. Color may be introduced later for specific semantic purposes
|
|
(e.g. error states) but the baseline is monochrome.
|
|
- **Text-first**: Every piece of information is presented as text. Balances are
|
|
numbers. Addresses are hex strings. Status is a sentence. No progress spinners
|
|
with animations — a text status line is sufficient.
|
|
- **Monospace font**: All text is rendered in the system monospace font.
|
|
Ethereum addresses, transaction hashes, and balances are inherently
|
|
fixed-width data. Rather than mixing proportional and monospace fonts, we use
|
|
monospace everywhere for visual consistency and alignment.
|
|
- **No images**: Zero image assets in the entire extension. No logos, no
|
|
illustrations, no token icons. Token identity is conveyed by symbol text (ETH,
|
|
USDC, etc.).
|
|
- **Tailwind CSS**: Utility-first CSS via Tailwind. No custom CSS classes for
|
|
styling. Tailwind is configured with a minimal monochrome palette. This keeps
|
|
the styling co-located with the markup and eliminates CSS file management.
|
|
- **Vanilla JS**: No framework (React, Vue, Svelte, etc.). The popup UI is small
|
|
enough that vanilla JS with simple view switching is sufficient. A framework
|
|
would add bundle size, build complexity, and attack surface for no benefit at
|
|
this scale.
|
|
- **360x600 popup**: Standard browser extension popup dimensions. The UI is
|
|
designed for this fixed viewport — no responsive breakpoints needed.
|
|
|
|
#### Language & Labeling
|
|
|
|
All user-facing text avoids crypto jargon wherever possible:
|
|
|
|
- "Recovery phrase" instead of "seed phrase", "mnemonic", or "BIP-39 mnemonic"
|
|
- "Address" instead of "account", "derived key", or "HD child"
|
|
- "Password" instead of "encryption key" or "vault passphrase"
|
|
- "Private key" instead of "secret key" or "signing key"
|
|
- Buttons use plain verbs: "Send", "Receive", "Copy address", "Add", "Back",
|
|
"Cancel", "Lock", "Unlock", "Allow", "Deny"
|
|
- No bracket notation like `[locked]` or `[setup]` — just plain titles
|
|
- Helpful inline descriptions where needed (e.g. "This password locks the wallet
|
|
on this device. It is not the same as your recovery phrase.")
|
|
- Error messages are full sentences ("Please enter your password." not "password
|
|
required")
|
|
|
|
#### Data Model
|
|
|
|
The core hierarchy is **Wallets → Addresses**:
|
|
|
|
- A **wallet** is either:
|
|
- An **HD wallet** (recovery phrase): generates multiple addresses from a
|
|
single 12/24 word recovery phrase using BIP-39/BIP-44 derivation. The user
|
|
can add more addresses with a "+" button.
|
|
- A **key wallet** (private key): a single address imported directly from a
|
|
private key. No "+" button since there is only one address.
|
|
- An **address** holds ETH and any user-added ERC-20 tokens.
|
|
- The user can have multiple wallets, each with multiple addresses (HD) or a
|
|
single address (key).
|
|
|
|
#### Navigation
|
|
|
|
The main view shows all addresses grouped by wallet, with ETH balances inline.
|
|
The user taps an address to see its detail view (full address, balance, tokens,
|
|
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
|
|
|
|
The popup has the following views, switched via simple show/hide:
|
|
|
|
1. **Lock**: Password input + Unlock button. Shown when the wallet is locked or
|
|
on first open after browser restart.
|
|
2. **Welcome**: Shown on first use. Three options: "Create a new wallet", "I
|
|
have a recovery phrase", "I have a private key". Password is set during this
|
|
first flow.
|
|
3. **Create**: Displays a generated 12-word recovery phrase with instructions to
|
|
write it down. User sets a password and confirms.
|
|
4. **Import recovery phrase**: Paste a 12 or 24 word recovery phrase. Password
|
|
fields shown only on first use.
|
|
5. **Import private key**: Paste a private key. Password fields shown only on
|
|
first use.
|
|
6. **Main**: All wallets listed, each showing its addresses with truncated
|
|
address and ETH balance. "+" next to HD wallets to add another address. "+
|
|
Add wallet" at the bottom. Settings and Lock buttons in the header. Future: a
|
|
sub-heading showing total portfolio value in USD (and eventually other
|
|
currencies).
|
|
7. **Add wallet**: Choose wallet type (new, recovery phrase, private key) — same
|
|
three options as Welcome but without password setup.
|
|
8. **Address detail**: Full address (click to copy), ETH balance, USD value
|
|
(future), Send/Receive buttons, token list with "+ Add" button.
|
|
9. **Send**: Token selector, recipient address, amount. Cancel returns to
|
|
address detail.
|
|
10. **Receive**: Full address displayed with "Copy address" button.
|
|
11. **Add token**: Enter contract address. The extension looks up the token
|
|
name/symbol automatically.
|
|
12. **Settings**: Network (RPC endpoint URL) with explanatory text.
|
|
13. **Approval**: When a website requests wallet access or a signature, shows
|
|
the site origin, request details, and Allow/Deny buttons.
|
|
|
|
### External Services
|
|
|
|
AutistMask is not a fully self-contained offline tool. It necessarily
|
|
communicates with external services to function as a wallet:
|
|
|
|
- **Ethereum JSON-RPC endpoint**: The extension needs an Ethereum node to query
|
|
balances (`eth_getBalance`), read ERC-20 token contracts (`eth_call`),
|
|
estimate gas (`eth_estimateGas`), fetch nonces (`eth_getTransactionCount`),
|
|
broadcast transactions (`eth_sendRawTransaction`), and check transaction
|
|
receipts. The default endpoint is a public RPC (configurable by the user to
|
|
any endpoint they prefer, including a local node). This is the only external
|
|
service the extension talks to.
|
|
|
|
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.
|
|
|
|
### Key Decisions
|
|
|
|
- **No framework**: The popup UI is vanilla JS and HTML. The extension is small
|
|
enough that a framework adds unnecessary complexity and attack surface.
|
|
- **Encrypted storage**: Seed phrases are encrypted with a user-provided
|
|
password using AES-256-GCM before being stored in the extension's local
|
|
storage. The encryption key is derived from the password using PBKDF2 with a
|
|
high iteration count.
|
|
- **BIP-39 / BIP-44**: Standard mnemonic generation and HD key derivation
|
|
(`m/44'/60'/0'/0/n`) for Ethereum address compatibility.
|
|
- **EIP-1193 provider**: The content script injects a `window.ethereum` object
|
|
that implements the EIP-1193 provider interface, enabling web3 site
|
|
connectivity.
|
|
- **Minimal RPC**: The extension communicates with Ethereum nodes via JSON-RPC.
|
|
The default endpoint is configurable. No Infura dependency — users can point
|
|
it at any Ethereum JSON-RPC endpoint.
|
|
|
|
### Supported Functionality
|
|
|
|
- Create new HD wallet (generates 12-word recovery phrase)
|
|
- Import HD wallet from existing 12 or 24 word recovery phrase
|
|
- Import single-address wallet from private key
|
|
- Add multiple addresses within an HD wallet
|
|
- Manage multiple wallets simultaneously
|
|
- View ETH balance per address
|
|
- View ERC-20 token balances (user adds token by contract address)
|
|
- Send ETH to an address
|
|
- Send ERC-20 tokens to an address
|
|
- Receive ETH/tokens (display address, copy to clipboard)
|
|
- Connect to web3 sites (EIP-1193 `eth_requestAccounts`)
|
|
- Sign transactions requested by connected sites
|
|
- Sign messages (`personal_sign`, `eth_sign`)
|
|
- Lock/unlock with password
|
|
- Configurable RPC endpoint
|
|
- Future: USD value display (and other fiat currencies)
|
|
|
|
### Non-Goals
|
|
|
|
- Token swaps (use a DEX in the browser)
|
|
- NFT display or management
|
|
- Multi-chain support (Ethereum mainnet only, for now)
|
|
- Analytics, telemetry, or tracking of any kind
|
|
- Advertisements or promotions
|
|
- Phishing detection
|
|
- Hardware wallet support (maybe later)
|
|
- Token list auto-discovery (user adds tokens manually)
|
|
- Fiat on/off ramps
|
|
- Browser notifications
|
|
- Transaction history (use Etherscan)
|
|
|
|
## TODO
|
|
|
|
- [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
|
|
- [ ] Security audit of key management
|
|
|
|
## License
|
|
|
|
GPL-3.0. See [LICENSE](LICENSE).
|
|
|
|
## Author
|
|
|
|
[@sneak](https://sneak.berlin)
|