@nomicfoundation/hardhat-viem
Version:
Hardhat plugin for viem
98 lines (82 loc) • 2.39 kB
text/typescript
import type { EthereumProvider } from "hardhat/types";
import type { Chain } from "viem";
import type { TestClientMode } from "../types";
import memoize from "lodash.memoize";
import {
UnknownDevelopmentNetworkError,
NetworkNotFoundError,
MultipleMatchingNetworksError,
} from "./errors";
export async function getChain(provider: EthereumProvider): Promise<Chain> {
const chains: Record<string, Chain> = require("viem/chains");
const chainId = await getChainId(provider);
if (isDevelopmentNetwork(chainId)) {
if (await isHardhatNetwork(provider)) {
return chains.hardhat;
} else if (await isFoundryNetwork(provider)) {
return chains.foundry;
} else {
throw new UnknownDevelopmentNetworkError();
}
}
const matchingChains = Object.values(chains).filter(
({ id }) => id === chainId
);
if (matchingChains.length === 0) {
if (await isHardhatNetwork(provider)) {
return {
...chains.hardhat,
id: chainId,
};
} else if (await isFoundryNetwork(provider)) {
return {
...chains.foundry,
id: chainId,
};
} else {
throw new NetworkNotFoundError(chainId);
}
}
if (matchingChains.length > 1) {
throw new MultipleMatchingNetworksError(chainId);
}
return matchingChains[0];
}
export function isDevelopmentNetwork(chainId: number) {
return chainId === 31337;
}
export async function getMode(
provider: EthereumProvider
): Promise<TestClientMode> {
if (await isHardhatNetwork(provider)) {
return "hardhat";
} else if (await isFoundryNetwork(provider)) {
return "anvil";
} else {
throw new UnknownDevelopmentNetworkError();
}
}
const getChainId = memoize(async (provider: EthereumProvider) =>
Number(await provider.send("eth_chainId"))
);
const isHardhatNetwork = memoize(async (provider: EthereumProvider) =>
detectNetworkByMethodName(provider, NetworkMethod.HARDHAT_METADATA)
);
const isFoundryNetwork = memoize(async (provider: EthereumProvider) =>
detectNetworkByMethodName(provider, NetworkMethod.ANVIL_NODE_INFO)
);
enum NetworkMethod {
HARDHAT_METADATA = "hardhat_metadata",
ANVIL_NODE_INFO = "anvil_nodeInfo",
}
async function detectNetworkByMethodName(
provider: EthereumProvider,
methodName: string
) {
try {
await provider.send(methodName);
return true;
} catch {
return false;
}
}