The Allow/Deny buttons did nothing because approval.init(ctx) was
called after the early return for approval mode, so listeners were
never attached. Move it before the check.
Rename view from "approve" to "approve-site" to avoid ambiguity with
future transaction approval. Space Allow and Deny buttons apart with
justify-between to prevent misclicks.
- Add activeAddress, allowedSites, deniedSites, rememberSiteChoice to
persisted state
- Replace auto-connect with permission checks: allowed sites connect
automatically, denied sites are rejected, unknown sites trigger an
approval popup
- Add approval popup UI with hostname display, active address preview,
remember checkbox, and allow/deny buttons
- Add ACTIVE/[select] indicator on address rows in the main view to
set the active web3 address
- Add allowed/denied site list management in settings with delete buttons
- Broadcast accountsChanged to connected dapps when active address changes
- Handle approval window close as implicit denial
Move truncateMiddle to helpers.js for reuse. Shorten displayed addresses
by 2 characters wherever a dot is shown: home view (40 char max), tx list
(maxAddr - 2), and address detail container (40ch width).
Deterministic colored dots derived from address bytes (16-color palette)
displayed before every address. ENS reverse resolution for transaction
counterparties with 12-hour localStorage cache.
- Rebuilt tx list rendering using innerHTML instead of createElement
- scrollbar-gutter: stable on body to prevent content shift
- max-width:42ch instead of width:42ch to prevent horizontal overflow
- overflow-x:hidden on body and #app
Left-side spans (age, address) get tailwind truncate class so they
can't push the row wider than its container. Right-side spans (direction,
amount) get shrink-0 so they keep their full text. Also added
overflow-hidden on #tx-list container.
The 42ch fixed-width spans with shrink-0 prevented flex from shrinking
them when the container was narrower, causing horizontal scrolling.
Also added overflow-x: hidden on body and #app as a safety net.
Transaction list entries are now two lines with more spacing:
- Line 1: humanized age (hover for ISO datetime) + direction (Sent/Received)
- Line 2: counterparty address + amount with symbol
- Clickable rows navigate to transaction detail view
Transaction detail view (placeholder) shows:
- Status, time, amount, from, to, transaction hash
- Back button returns to address detail
Also added "transaction" to VIEWS list in helpers.
Major changes:
- Fetch token balances and tx history from Blockscout API (configurable)
- Remove manual token discovery (discoverTokens) in favor of Blockscout
- HD address gap scanning on mnemonic import
- Duplicate mnemonic detection on wallet add
- EIP-6963 multi-wallet discovery + selectedAddress updates in inpage
- Two-tier balance refresh: 10s while popup open, 60s background
- Fix $0.00 flash before prices load (return null when no prices)
- No-layout-shift: min-height on total value element
- Aligned balance columns (42ch address width, consistent USD column)
- All errors use flash messages instead of off-screen error divs
- Settings gear in global title bar, add-wallet moved to settings pane
- Settings wells with light grey background, configurable Blockscout URL
- Consistent "< Back" buttons top-left on all views
- Address titles (Address 1.1, 1.2, etc.) on main and detail views
- Send view shows current balance of selected asset
- Clickable affordance policy added to README
- Shortened mnemonic backup warning
- Fix broken background script constant imports
Total USD value displayed in 2x type above wallet list on Home.
Value aggregation: getAddressValueUsd (ETH + all tokens) →
getWalletValueUsd → getTotalValueUsd. Price API cached for 5
minutes, balance fetches cached for 60 seconds. Both caches
are app-wide — repeated calls to refreshPrices/refreshBalances
are no-ops within the TTL.
Move "AutistMask by @sneak" to a global title bar that appears
on every screen. Per-view headings demoted to h2 sub-headings.
Settings button moved to bottom of main view alongside Add
wallet. In DEBUG mode, the red banner now shows the current
screen name in parentheses (e.g. "DEBUG / INSECURE (main)").
Shows the top 25 tokens by market cap as clickable buttons
below the contract address input. Clicking a token fills in
its contract address automatically.
vault.js: Argon2id key derivation + XSalsa20-Poly1305 encryption
via libsodium-wrappers-sumo. No raw crypto primitives.
Wallet creation now requires a password. The mnemonic or private
key is encrypted before storage — only the ciphertext blob
(salt, nonce, ciphertext) is persisted. The plaintext secret
is never stored.
Sending requires the password to decrypt the secret, derive
the signing key, and construct the transaction. Wrong password
is caught and reported.
Send: stores mnemonic/private key with wallet data, derives
signing key from mnemonic + address index via ethers HDNodeWallet,
constructs transaction with parseEther, broadcasts via
sendTransaction, waits for confirmation, shows block number
and tx hash. ENS resolution in To field preserved.
Receive: QR code rendered to canvas via qrcode library (1.5.4).
Shows scannable QR above the full address text.
README updated with qrcode dependency and TODO progress.
Reverse ENS lookup on balance refresh — if an address has an
ENS name, it's shown in the wallet list and address detail view.
Send form accepts ENS names in the To field (resolves before
sending). Placeholder updated to indicate ENS support.
Xpubs and derived addresses stored unencrypted in extension
storage for instant read-only access without a password.
Password will only be required for signing transactions
(not yet implemented). Real addresses now derived from
mnemonic via ethers HDNodeWallet at wallet creation time.
Removed lock screen, password fields, and Lock button.
BIP-39 mnemonic validation added. README updated with split
storage model documentation.
- Password help text now explains it encrypts the recovery phrase
on disk and is not used for address derivation
- Die button generates cryptographically random phrases using
crypto.getRandomValues(), different each click
- "roll the die for a new one" wording
- README documents full encryption scheme (PBKDF2 + AES-256-GCM)
and explicitly notes password is not part of BIP-39 derivation
Welcome and main views now show one button: "Add wallet".
Private key import is accessible as a small link at the bottom
of the Add Wallet view ("Have a private key instead?").
Merge "Create new wallet" and "Import recovery phrase" into one
"Add wallet" screen. The recovery phrase textarea starts empty.
A clickable die button generates a random phrase and shows a
backup warning. Users who already have a phrase just paste it.
Welcome screen simplified to two options: "Add wallet" and
"Import private key". README updated to match.
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.
Makefile, Dockerfile, CI workflow, prettier config, manifests for
Chrome (MV3) and Firefox (MV2), source directory structure, and
minimal test suite. All checks pass.