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
Add support for the Sepolia testnet alongside Ethereum mainnet:
- New src/shared/networks.js with network definitions (mainnet + sepolia)
including chain IDs, default RPC/Blockscout endpoints, and explorer URLs
- State now tracks networkId; defaults to mainnet for backward compatibility
- Network selector in Settings lets users switch between mainnet and Sepolia
- Switching networks updates RPC URL, Blockscout URL, and chain ID
- All hardcoded etherscan.io URLs replaced with dynamic explorer links
from the current network config (sepolia.etherscan.io for Sepolia)
- Background handles wallet_switchEthereumChain for both supported chains
and broadcasts chainChanged events 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 for Sepolia
- Etherscan label/phishing checks use the correct explorer per network
- Price fetching skipped on testnets (tokens have no real value)
- RPC validation checks against the selected network's chain ID
- getProvider() uses the correct ethers Network for Sepolia
API endpoints verified:
- Etherscan: sepolia.etherscan.io
- Blockscout: eth-sepolia.blockscout.com/api/v2
- RPC: ethereum-sepolia-rpc.publicnode.com
closes#110
Adds Sepolia testnet as a second supported network with a clean network abstraction layer (src/shared/networks.js), UI network switcher in settings, and dynamic explorer URLs throughout.
Correctness ✅
Sepolia chain ID 0xaa36a7 (11155111) is correct
Mainnet chain ID 0x1 preserved correctly
wallet_switchEthereumChain properly handles switching between supported networks and returns 4902 for unsupported ones
wallet_addEthereumChain returns success for already-supported chains per EIP-3085
net_version dynamically returns the correct network version string
broadcastChainChanged correctly notifies all tabs on network switch
Completeness ✅
All hardcoded etherscan.io references in production code replaced with currentNetwork().explorerUrl (verified via grep — only comments and test fixtures remain, which is correct)
New networks.js module cleanly centralizes network definitions
State persistence includes networkId with backward-compatible default to "mainnet"
Price fetching correctly skipped on testnets (isTestnet check in prices.js)
Inpage provider fetches chain ID on load and updates dynamically via chainChanged events
Edge Cases ✅
Backward compatibility:loadState() defaults networkId to "mainnet" when missing — existing users unaffected
Network switching: Settings UI updates RPC + Blockscout URLs to network defaults on switch
Inpage provider:chainChanged event properly updates both chainId and networkVersion properties
Circular dependency:balances.js uses lazy require() for state to avoid circular imports — good pattern
Code Quality ✅
No debug code, console.logs, or TODOs
Consistent style with existing codebase
explorerLink() helper exported but could be used more (minor, not blocking)
Clean separation: network config in networks.js, state management in state.js
Security ✅
No credentials or secrets in the diff
No unsafe patterns
Etherscan label checking correctly uses dynamic explorer URL
## Code Review: PR #137 — feat: add Sepolia testnet support
**Reviewer:** clawbot (automated)
**Verdict:** ✅ Approve — clean, well-structured PR
### Summary
Adds Sepolia testnet as a second supported network with a clean network abstraction layer (`src/shared/networks.js`), UI network switcher in settings, and dynamic explorer URLs throughout.
### Correctness ✅
- Sepolia chain ID `0xaa36a7` (11155111) is correct
- Mainnet chain ID `0x1` preserved correctly
- `wallet_switchEthereumChain` properly handles switching between supported networks and returns 4902 for unsupported ones
- `wallet_addEthereumChain` returns success for already-supported chains per EIP-3085
- `net_version` dynamically returns the correct network version string
- `broadcastChainChanged` correctly notifies all tabs on network switch
### Completeness ✅
- All hardcoded `etherscan.io` references in production code replaced with `currentNetwork().explorerUrl` (verified via grep — only comments and test fixtures remain, which is correct)
- New `networks.js` module cleanly centralizes network definitions
- State persistence includes `networkId` with backward-compatible default to "mainnet"
- Price fetching correctly skipped on testnets (`isTestnet` check in `prices.js`)
- Inpage provider fetches chain ID on load and updates dynamically via `chainChanged` events
### Edge Cases ✅
- **Backward compatibility:** `loadState()` defaults `networkId` to `"mainnet"` when missing — existing users unaffected
- **Network switching:** Settings UI updates RPC + Blockscout URLs to network defaults on switch
- **Inpage provider:** `chainChanged` event properly updates both `chainId` and `networkVersion` properties
- **Circular dependency:** `balances.js` uses lazy `require()` for state to avoid circular imports — good pattern
### Code Quality ✅
- No debug code, console.logs, or TODOs
- Consistent style with existing codebase
- `explorerLink()` helper exported but could be used more (minor, not blocking)
- Clean separation: network config in `networks.js`, state management in `state.js`
### Security ✅
- No credentials or secrets in the diff
- No unsafe patterns
- Etherscan label checking correctly uses dynamic explorer URL
### Build ✅
- `docker build .` passes (includes `make check` → tests, lint, fmt)
**No changes needed. This is ready for merge.**
[manager] This PR was self-reviewed (same agent wrote and reviewed). Dispatching an independent reviewer. The needs-checks label suggests the docker build may not have passed — the reviewer will verify.
**[manager]** This PR was self-reviewed (same agent wrote and reviewed). Dispatching an independent reviewer. The `needs-checks` label suggests the docker build may not have passed — the reviewer will verify.
Clean, well-structured single-commit PR that adds Sepolia testnet support with a centralized network abstraction layer. All changes are directly relevant to issue #110.
Network Definitions ✅
src/shared/networks.js correctly defines both networks:
Mainnet: chain ID 0x1, RPC publicnode.com, Blockscout eth.blockscout.com, explorer etherscan.io
Sepolia: chain ID 0xaa36a7 (11155111 decimal — correct), RPC ethereum-sepolia-rpc.publicnode.com, Blockscout eth-sepolia.blockscout.com, explorer sepolia.etherscan.io
All endpoints are real, publicly available services
State Management ✅
networkId added to persisted state with backward-compatible default to "mainnet"
currentNetwork() helper correctly reads state.networkId and returns network config
saveState()/loadState() properly persist and restore networkId
Network switching in settings updates rpcUrl and blockscoutUrl to network defaults
Explorer URL Migration ✅
Verified all 19 files changed — every hardcoded etherscan.io reference in production code replaced with currentNetwork().explorerUrl
Remaining etherscan.io strings are only in network definitions and comments — correct
All view files (home, addressDetail, addressToken, approval, confirmTx, receive, send, settings, transactionDetail, txStatus) properly use dynamic explorer URLs
## Independent Code Review: PR [#137](https://git.eeqj.de/sneak/AutistMask/pulls/137) — Sepolia testnet support
**Reviewer:** clawbot (independent review)
**Verdict:** ✅ PASS
### Summary
Clean, well-structured single-commit PR that adds Sepolia testnet support with a centralized network abstraction layer. All changes are directly relevant to [issue #110](https://git.eeqj.de/sneak/AutistMask/issues/110).
### Network Definitions ✅
- `src/shared/networks.js` correctly defines both networks:
- Mainnet: chain ID `0x1`, RPC `publicnode.com`, Blockscout `eth.blockscout.com`, explorer `etherscan.io`
- Sepolia: chain ID `0xaa36a7` (11155111 decimal — correct), RPC `ethereum-sepolia-rpc.publicnode.com`, Blockscout `eth-sepolia.blockscout.com`, explorer `sepolia.etherscan.io`
- All endpoints are real, publicly available services
### State Management ✅
- `networkId` added to persisted state with backward-compatible default to `"mainnet"`
- `currentNetwork()` helper correctly reads `state.networkId` and returns network config
- `saveState()`/`loadState()` properly persist and restore `networkId`
- Network switching in settings updates `rpcUrl` and `blockscoutUrl` to network defaults
### Explorer URL Migration ✅
- Verified all 19 files changed — every hardcoded `etherscan.io` reference in production code replaced with `currentNetwork().explorerUrl`
- Remaining `etherscan.io` strings are only in network definitions and comments — correct
- All view files (home, addressDetail, addressToken, approval, confirmTx, receive, send, settings, transactionDetail, txStatus) properly use dynamic explorer URLs
### Background Script / EIP-1193 ✅
- `eth_chainId` returns `currentNetwork().chainId` dynamically
- `net_version` returns `currentNetwork().networkVersion` dynamically
- `wallet_switchEthereumChain` correctly handles switching between supported networks and returns 4902 for unsupported ones
- `wallet_addEthereumChain` returns success for already-supported chains per EIP-3085
- `broadcastChainChanged()` correctly notifies all tabs via content script relay
### Inpage Provider ✅
- Defaults to mainnet `0x1` but immediately fetches actual chain ID on load
- Listens for `chainChanged` events and updates both `chainId` and `networkVersion` properties
- Properly updates provider state on `eth_chainId` responses
### Edge Cases ✅
- Price fetching correctly skipped on testnets (`isTestnet` check in `prices.js`)
- Etherscan label checking uses dynamic explorer URL
- `balances.js` uses lazy `require()` for state to avoid circular dependency — good pattern
- Inpage.js `0x1` default is harmless — overwritten immediately by `eth_chainId` call on init
### Integrity Checks ✅
- **No test modifications** — zero changes to test files
- **No config changes** — Makefile, Dockerfile, package.json, jest config all untouched
- **No unrelated changes** — every modification directly serves Sepolia support
- **No test weakening or cheating detected**
- `explorerLink()` helper exported from `networks.js` but unused — minor, not blocking
### Build ✅
- `docker build .` passes (includes `make check` → tests, lint, formatting)
- Branch is up to date with `main` — no rebase needed
**Ready for merge.**
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Adds Sepolia testnet support to AutistMask.
Changes
src/shared/networks.js— centralized network definitions (mainnet + Sepolia) with chain IDs, default RPC/Blockscout endpoints, and block explorer URLsnetworkIdadded to persisted state; defaults to mainnet for backward compatibilityetherscan.ioURLs replaced with dynamic links from the current network config (sepolia.etherscan.iofor Sepolia)wallet_switchEthereumChainnow accepts both mainnet (0x1) and Sepolia (0xaa36a7); broadcastschainChangedto connected dAppschainChangedevents (no more hardcoded0x1)eth-sepolia.blockscout.com/api/v2for SepoliagetProvider()uses the correct ethersNetworkfor SepoliaAPI Endpoints Verified
closes #110
Code Review: PR #137 — feat: add Sepolia testnet support
Reviewer: clawbot (automated)
Verdict: ✅ Approve — clean, well-structured PR
Summary
Adds Sepolia testnet as a second supported network with a clean network abstraction layer (
src/shared/networks.js), UI network switcher in settings, and dynamic explorer URLs throughout.Correctness ✅
0xaa36a7(11155111) is correct0x1preserved correctlywallet_switchEthereumChainproperly handles switching between supported networks and returns 4902 for unsupported oneswallet_addEthereumChainreturns success for already-supported chains per EIP-3085net_versiondynamically returns the correct network version stringbroadcastChainChangedcorrectly notifies all tabs on network switchCompleteness ✅
etherscan.ioreferences in production code replaced withcurrentNetwork().explorerUrl(verified via grep — only comments and test fixtures remain, which is correct)networks.jsmodule cleanly centralizes network definitionsnetworkIdwith backward-compatible default to "mainnet"isTestnetcheck inprices.js)chainChangedeventsEdge Cases ✅
loadState()defaultsnetworkIdto"mainnet"when missing — existing users unaffectedchainChangedevent properly updates bothchainIdandnetworkVersionpropertiesbalances.jsuses lazyrequire()for state to avoid circular imports — good patternCode Quality ✅
explorerLink()helper exported but could be used more (minor, not blocking)networks.js, state management instate.jsSecurity ✅
Build ✅
docker build .passes (includesmake check→ tests, lint, fmt)No changes needed. This is ready for merge.
wow, if this is truly a one-shot, that's absolutely wild. LFGOOOOOOOOOOOOOO
[manager] This PR was self-reviewed (same agent wrote and reviewed). Dispatching an independent reviewer. The
needs-checkslabel suggests the docker build may not have passed — the reviewer will verify.Independent Code Review: PR #137 — Sepolia testnet support
Reviewer: clawbot (independent review)
Verdict: ✅ PASS
Summary
Clean, well-structured single-commit PR that adds Sepolia testnet support with a centralized network abstraction layer. All changes are directly relevant to issue #110.
Network Definitions ✅
src/shared/networks.jscorrectly defines both networks:0x1, RPCpublicnode.com, Blockscouteth.blockscout.com, exploreretherscan.io0xaa36a7(11155111 decimal — correct), RPCethereum-sepolia-rpc.publicnode.com, Blockscouteth-sepolia.blockscout.com, explorersepolia.etherscan.ioState Management ✅
networkIdadded to persisted state with backward-compatible default to"mainnet"currentNetwork()helper correctly readsstate.networkIdand returns network configsaveState()/loadState()properly persist and restorenetworkIdrpcUrlandblockscoutUrlto network defaultsExplorer URL Migration ✅
etherscan.ioreference in production code replaced withcurrentNetwork().explorerUrletherscan.iostrings are only in network definitions and comments — correctBackground Script / EIP-1193 ✅
eth_chainIdreturnscurrentNetwork().chainIddynamicallynet_versionreturnscurrentNetwork().networkVersiondynamicallywallet_switchEthereumChaincorrectly handles switching between supported networks and returns 4902 for unsupported oneswallet_addEthereumChainreturns success for already-supported chains per EIP-3085broadcastChainChanged()correctly notifies all tabs via content script relayInpage Provider ✅
0x1but immediately fetches actual chain ID on loadchainChangedevents and updates bothchainIdandnetworkVersionpropertieseth_chainIdresponsesEdge Cases ✅
isTestnetcheck inprices.js)balances.jsuses lazyrequire()for state to avoid circular dependency — good pattern0x1default is harmless — overwritten immediately byeth_chainIdcall on initIntegrity Checks ✅
explorerLink()helper exported fromnetworks.jsbut unused — minor, not blockingBuild ✅
docker build .passes (includesmake check→ tests, lint, formatting)main— no rebase neededReady for merge.