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

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
This commit is contained in:
user
2026-03-01 10:45:21 -08:00
parent d35bfb7d23
commit d4f2f34c89
19 changed files with 272 additions and 56 deletions

View File

@@ -2,7 +2,10 @@
// Creates window.ethereum (EIP-1193 provider) and announces via EIP-6963.
(function () {
const CHAIN_ID = "0x1"; // Ethereum mainnet
// Defaults to mainnet; updated dynamically via eth_chainId on init and
// chainChanged events from the extension.
let currentChainId = "0x1";
let currentNetworkVersion = "1";
const listeners = {};
let nextId = 1;
@@ -28,6 +31,12 @@
if (event.source !== window) return;
if (event.data?.type !== "AUTISTMASK_EVENT") return;
const { eventName, data } = event.data;
if (eventName === "chainChanged") {
currentChainId = data;
currentNetworkVersion = String(parseInt(data, 16));
provider.chainId = currentChainId;
provider.networkVersion = currentNetworkVersion;
}
emit(eventName, data);
});
@@ -57,8 +66,8 @@
const provider = {
isAutistMask: true,
isMetaMask: true, // compatibility — many dApps check this
chainId: CHAIN_ID,
networkVersion: "1",
chainId: currentChainId,
networkVersion: currentNetworkVersion,
selectedAddress: null,
async request(args) {
@@ -75,6 +84,12 @@
? result[0]
: null;
}
if (args.method === "eth_chainId" && result) {
currentChainId = result;
currentNetworkVersion = String(parseInt(result, 16));
provider.chainId = currentChainId;
provider.networkVersion = currentNetworkVersion;
}
return result;
},
@@ -189,4 +204,19 @@
window.addEventListener("eip6963:requestProvider", announceProvider);
announceProvider();
// Fetch the current chain ID from the extension on load so the provider
// reflects the selected network immediately (covers Sepolia etc.).
sendRequest({ method: "eth_chainId", params: [] })
.then((chainId) => {
if (chainId) {
currentChainId = chainId;
currentNetworkVersion = String(parseInt(chainId, 16));
provider.chainId = currentChainId;
provider.networkVersion = currentNetworkVersion;
}
})
.catch(() => {
// Best-effort — keep defaults.
});
})();