@nomicfoundation/hardhat-viem
Version:
Hardhat plugin for viem
177 lines (159 loc) • 5.61 kB
text/typescript
import type { EthereumProvider } from "hardhat/types";
import type {
Address,
Chain,
PublicClientConfig,
WalletClientConfig,
TestClientConfig,
} from "viem";
import type {
PublicClient,
TestClient,
TestClientMode,
WalletClient,
} from "../types";
async function getParameters<TConfig extends {} | undefined>(
chain: Chain,
config: TConfig
) {
const { isDevelopmentNetwork } = await import("./chains");
const defaultParameters = isDevelopmentNetwork(chain.id)
? { pollingInterval: 50, cacheTime: 0 }
: {};
const transportParameters = isDevelopmentNetwork(chain.id)
? { retryCount: 0 }
: {};
return {
clientParameters: { ...defaultParameters, ...config },
transportParameters,
};
}
/**
* Get a PublicClient instance. This is a read-only client that can be used to
* query the blockchain.
*
* @param provider The Ethereum provider used to connect to the blockchain.
* @param publicClientConfig Optional configuration for the PublicClient instance. See the viem documentation for more information.
* @returns A PublicClient instance.
*/
export async function getPublicClient(
provider: EthereumProvider,
publicClientConfig?: Partial<PublicClientConfig>
): Promise<PublicClient> {
const { getChain } = await import("./chains");
const chain = publicClientConfig?.chain ?? (await getChain(provider));
return innerGetPublicClient(provider, chain, publicClientConfig);
}
export async function innerGetPublicClient(
provider: EthereumProvider,
chain: Chain,
publicClientConfig?: Partial<PublicClientConfig>
): Promise<PublicClient> {
const viem = await import("viem");
const { clientParameters, transportParameters } = await getParameters(
chain,
publicClientConfig
);
const publicClient = viem.createPublicClient({
chain,
transport: viem.custom(provider, transportParameters),
...clientParameters,
});
return publicClient;
}
/**
* Get a list of WalletClient instances. These are read-write clients that can
* be used to send transactions to the blockchain. Each client is associated
* with an account obtained from the provider using `eth_accounts`.
*
* @param provider The Ethereum provider used to connect to the blockchain.
* @param walletClientConfig Optional configuration for the WalletClient instances. See the viem documentation for more information.
* @returns A list of WalletClient instances.
*/
export async function getWalletClients(
provider: EthereumProvider,
walletClientConfig?: Partial<WalletClientConfig>
): Promise<WalletClient[]> {
const { getAccounts } = await import("./accounts");
const { getChain } = await import("./chains");
const chain = walletClientConfig?.chain ?? (await getChain(provider));
const accounts = await getAccounts(provider);
return innerGetWalletClients(provider, chain, accounts, walletClientConfig);
}
export async function innerGetWalletClients(
provider: EthereumProvider,
chain: Chain,
accounts: Address[],
walletClientConfig?: Partial<WalletClientConfig>
): Promise<WalletClient[]> {
const viem = await import("viem");
const { clientParameters, transportParameters } = await getParameters(
chain,
walletClientConfig
);
const walletClients = accounts.map((account) =>
viem.createWalletClient({
chain,
account,
transport: viem.custom(provider, transportParameters),
...clientParameters,
})
);
return walletClients;
}
/**
* Get a WalletClient instance for a specific address. This is a read-write
* client that can be used to send transactions to the blockchain.
*
* @param provider The Ethereum provider used to connect to the blockchain.
* @param address The public address of the account to use.
* @param walletClientConfig Optional configuration for the WalletClient instance. See the viem documentation for more information.
* @returns A WalletClient instance.
*/
export async function getWalletClient(
provider: EthereumProvider,
address: Address,
walletClientConfig?: Partial<WalletClientConfig>
): Promise<WalletClient> {
const { getChain } = await import("./chains");
const chain = walletClientConfig?.chain ?? (await getChain(provider));
return (
await innerGetWalletClients(provider, chain, [address], walletClientConfig)
)[0];
}
/**
* Get a TestClient instance. This is a read-write client that can be used to
* perform actions only available on test nodes such as hardhat or anvil.
*
* @param provider The Ethereum provider used to connect to the blockchain.
* @param testClientConfig Optional configuration for the TestClient instance. See the viem documentation for more information.
* @returns A TestClient instance.
*/
export async function getTestClient(
provider: EthereumProvider,
testClientConfig?: Partial<TestClientConfig>
): Promise<TestClient> {
const { getChain, getMode } = await import("./chains");
const chain = testClientConfig?.chain ?? (await getChain(provider));
const mode = await getMode(provider);
return innerGetTestClient(provider, chain, mode, testClientConfig);
}
export async function innerGetTestClient(
provider: EthereumProvider,
chain: Chain,
mode: TestClientMode,
testClientConfig?: Partial<TestClientConfig>
): Promise<TestClient> {
const viem = await import("viem");
const { clientParameters, transportParameters } = await getParameters(
chain,
testClientConfig
);
const testClient = viem.createTestClient({
mode,
chain,
transport: viem.custom(provider, transportParameters),
...clientParameters,
});
return testClient;
}