// 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),
);

// Thrown rather than defaulted. An id this build does not know used to answer
// with MAINNET, so a stored `{networkId:"base"}` rendered the selector as
// Ethereum Mainnet with no banner and answered eth_chainId 0x1, while rpcUrl
// still pointed at Base — the wallet telling the user and the page one chain
// while transacting on another. Nothing in this codebase has an unknown id to
// offer: stored state is validated against this table before it is loaded
// (src/shared/stateSchema.js), and every other caller passes an id it took
// from here. So an unknown id is a defect, and it says so, the same way
// getProvider() (src/shared/balances.js) already refuses one.
class UnknownNetworkError extends Error {
    constructor(id) {
        super(
            "AutistMask does not know the network " +
                JSON.stringify(id) +
                "; it supports " +
                Object.keys(NETWORKS).join(", "),
        );
        this.name = "UnknownNetworkError";
        this.networkId = id;
    }
}

// Own properties only: NETWORKS inherits from Object.prototype, so
// NETWORKS["constructor"] and NETWORKS["__proto__"] both answer with something
// truthy that is not a network. A stored id is untrusted input, and this is
// the test the validator uses to decide whether it may be adopted at all.
function isKnownNetworkId(id) {
    return (
        typeof id === "string" &&
        Object.prototype.hasOwnProperty.call(NETWORKS, id)
    );
}

function networkById(id) {
    if (!isKnownNetworkId(id)) throw new UnknownNetworkError(id);
    return NETWORKS[id];
}

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,
    UnknownNetworkError,
    isKnownNetworkId,
    networkById,
    networkByChainId,
    explorerLink,
};
