feat: add Sepolia testnet support (#137)
All checks were successful
check / check (push) Successful in 9s

## 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>
This commit was merged in pull request #137.
This commit is contained in:
2026-03-01 20:11:22 +01:00
committed by Jeffrey Paul
parent d35bfb7d23
commit e53420f2e2
19 changed files with 272 additions and 56 deletions

57
src/shared/networks.js Normal file
View File

@@ -0,0 +1,57 @@
// Network definitions for supported Ethereum networks.
// Each network specifies its chain ID, default RPC and Blockscout endpoints,
// and the block explorer base URL used for address/tx/token/block links.
const NETWORKS = {
mainnet: {
id: "mainnet",
name: "Ethereum Mainnet",
chainId: "0x1",
networkVersion: "1",
nativeCurrency: "ETH",
defaultRpcUrl: "https://ethereum-rpc.publicnode.com",
defaultBlockscoutUrl: "https://eth.blockscout.com/api/v2",
explorerUrl: "https://etherscan.io",
isTestnet: false,
},
sepolia: {
id: "sepolia",
name: "Sepolia Testnet",
chainId: "0xaa36a7",
networkVersion: "11155111",
nativeCurrency: "SepoliaETH",
defaultRpcUrl: "https://ethereum-sepolia-rpc.publicnode.com",
defaultBlockscoutUrl: "https://eth-sepolia.blockscout.com/api/v2",
explorerUrl: "https://sepolia.etherscan.io",
isTestnet: true,
},
};
const SUPPORTED_CHAIN_IDS = new Set(
Object.values(NETWORKS).map((n) => n.chainId),
);
function networkById(id) {
return NETWORKS[id] || NETWORKS.mainnet;
}
function networkByChainId(chainId) {
for (const net of Object.values(NETWORKS)) {
if (net.chainId === chainId) return net;
}
return null;
}
// Build a block explorer link for the given path type and value.
// type: "address" | "tx" | "token" | "block"
function explorerLink(network, type, value) {
return `${network.explorerUrl}/${type}/${value}`;
}
module.exports = {
NETWORKS,
SUPPORTED_CHAIN_IDS,
networkById,
networkByChainId,
explorerLink,
};