## Summary
Adds Sepolia testnet support to AutistMask.
### Changes
- **New `src/shared/networks.js`** — centralized network definitions (mainnet + Sepolia) with chain IDs, default RPC/Blockscout endpoints, and block explorer URLs
- **State management** — `networkId` added to persisted state; defaults to mainnet for backward compatibility
- **Settings UI** — network selector dropdown lets users switch between Ethereum Mainnet and Sepolia Testnet
- **Dynamic explorer links** — all hardcoded `etherscan.io` URLs replaced with dynamic links from the current network config (`sepolia.etherscan.io` for Sepolia)
- **Background service** — `wallet_switchEthereumChain` now accepts both mainnet (0x1) and Sepolia (0xaa36a7); broadcasts `chainChanged` to connected dApps
- **Inpage provider** — fetches chain ID on init and updates dynamically via `chainChanged` events (no more hardcoded `0x1`)
- **Blockscout API** — uses `eth-sepolia.blockscout.com/api/v2` for Sepolia
- **Etherscan labels** — phishing/scam checks use the correct explorer per network
- **Price fetching** — skipped on testnets (testnet tokens have no real market value)
- **RPC validation** — checks against the selected network's chain ID, not hardcoded mainnet
- **ethers provider** — `getProvider()` uses the correct ethers `Network` for Sepolia
### API Endpoints Verified
| Service | Mainnet | Sepolia |
|---------|---------|--------|
| Etherscan | etherscan.io | sepolia.etherscan.io |
| Blockscout | eth.blockscout.com/api/v2 | eth-sepolia.blockscout.com/api/v2 |
| RPC | ethereum-rpc.publicnode.com | ethereum-sepolia-rpc.publicnode.com |
| CoinDesk (prices) | ✅ | N/A (skipped on testnet) |
closes#110
Reviewed-on: #137
THIS WAS ONESHOTTED USING OPUS 4. WTAF
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
Expands the confirm-tx warning system with three new warning types, all using the existing `visibility:hidden/visible` pattern from PR #98 (no animations, no layout shift).
## Changes
1. **Scam address list expanded** (7 → 652 addresses): Sourced from [MyEtherWallet/ethereum-lists](https://github.com/MyEtherWallet/ethereum-lists) darklist (MIT license). Checked synchronously before sending.
2. **Contract address warning**: When the recipient is a smart contract (detected via `getCode`), shows a warning that sending directly to a contract may result in permanent loss of funds.
3. **Null/burn address warning**: Detects known burn addresses (`0x0000...0000`, `0x...dead`, `0x...deadbeef`) and warns that funds are permanently destroyed.
4. **No-history warning** (existing from #98): Unchanged, still shows for EOAs with zero transaction history.
All warnings use reserved-space `visibility:hidden/visible` elements — no layout shift, no animations.
closes#114
Co-authored-by: clawbot <clawbot@noreply.git.eeqj.de>
Co-authored-by: user <user@Mac.lan guest wan>
Co-authored-by: clawbot <clawbot@eeqj.de>
Reviewed-on: #118
Co-authored-by: clawbot <sneak+clawbot@sneak.cloud>
Co-committed-by: clawbot <sneak+clawbot@sneak.cloud>
action.openPopup() is unreliable when called from the background script
during an async message handler — it requires a user gesture context.
tx and sign approvals are triggered programmatically by dApp RPC calls,
not by user clicking the toolbar icon, so openPopup() fails silently.
Use windows.create() directly for tx/sign approvals, matching the
standard extension pattern (used by MetaMask and others). Site-connection
approvals retain openPopup() since they can fall back to the user
clicking the toolbar icon.
Also updates popup window dimensions to 360x600 to match the standard
popup viewport specified in README.
Closes#4
Replace stub error handlers with full approval flow for personal_sign,
eth_sign, eth_signTypedData_v4, and eth_signTypedData. Uses toolbar
popup only (no fallback window) and keeps sign approvals pending across
popup close/reopen cycles so the user can respond via the toolbar icon.
Token balances from Blockscout are now filtered before display.
A token only appears if it meets at least one criterion:
- In the known 511-token list (by contract address)
- Explicitly tracked by the user (added via + Token)
- Has >= 1,000 holders on-chain
Also rejects tokens spoofing a known symbol from a different
contract address (same check used for transaction filtering).
This prevents airdropped spam tokens like "OpenClaw" from
appearing in the wallet without the user ever tracking them.
Previously the approval popup closed immediately after the user
entered their password, giving zero feedback about whether the
transaction was broadcast or confirmed. Now:
1. Background sends the broadcast result back to the popup via
sendResponse callback (txHash or error)
2. Popup shows wait-tx screen on success (with polling timer)
or error-tx screen on failure
3. Wait-tx polls for confirmation and transitions to success-tx
4. Done button closes the approval window
txStatus.init() moved before the approval early-return so the
wait/success/error views are wired up in the approval popup.
Done buttons detect the approval context and call window.close()
instead of navigating to address detail.
Show a confirmation popup with tx details (from, to, value, data) and
password prompt when a dApp calls eth_sendTransaction. Sign and broadcast
the transaction in the background, returning the tx hash to the dApp.
Add debugFetch wrapper in log.js that logs method, URL, and body on
request, and status code on response. Replace all fetch() calls
across balances, transactions, tokens, background RPC proxy, and
settings validation with debugFetch.
Use action.openPopup() to show the approval in the toolbar popup,
which is anchored to the browser window and cannot trigger a macOS
Space switch. Falls back to a separate window if openPopup() is
unavailable. A port connection detects when the popup is dismissed
without a response, and the popup URL is reset to the main UI after
every approval resolution.
Use getLastFocused to find the current Chrome window and position the
approval popup centered over it. This keeps the popup on the same
macOS virtual desktop instead of switching Spaces.
When switching addresses, reject and close any open approval popup
windows so their promises don't hang forever. Without this, stale
pending approvals from automatic dapp reconnection attempts block
future connection requests.
Non-remembered approvals should not survive switching to a different
address and back. Wipe connectedSites when broadcasting
accountsChanged so temporary approvals require re-prompting.
When the active address changes, each tab now receives either the new
address (if permitted) or an empty array (if not). This prevents dapps
from seeing an address they have no permission for, which caused them
to break.
allowedSites and deniedSites are now objects keyed by address instead
of flat arrays, so approving a site for one address no longer grants
access for all addresses. Old flat-array data is discarded on load.
Settings view collects unique hostnames across all addresses and
deleting removes the site from every address.
- 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
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
Three-part architecture:
- inpage.js: creates window.ethereum in page context with
request(), on(), send(), sendAsync(), enable() methods.
Sets isMetaMask=true for compatibility.
- content/index.js: bridge between page and extension via
postMessage (page<->content) and runtime.sendMessage
(content<->background).
- background/index.js: handles RPC routing. Proxies read-only
methods (eth_call, eth_getBalance, etc.) to configured RPC.
Handles eth_requestAccounts (auto-connect for now),
wallet_switchEthereumChain (mainnet only), and returns
informative errors for unimplemented signing methods.
Manifests updated with web_accessible_resources for inpage.js.
Build updated to bundle inpage.js as a separate output file.
Makefile, Dockerfile, CI workflow, prettier config, manifests for
Chrome (MV3) and Firefox (MV2), source directory structure, and
minimal test suite. All checks pass.