@nomicfoundation/hardhat-viem 2.0.5 → 3.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/LICENSE +4 -16
  2. package/README.md +35 -247
  3. package/dist/src/index.d.ts +5 -0
  4. package/dist/src/index.d.ts.map +1 -0
  5. package/dist/src/index.js +10 -0
  6. package/dist/src/index.js.map +1 -0
  7. package/dist/src/internal/accounts.d.ts +4 -0
  8. package/dist/src/internal/accounts.d.ts.map +1 -0
  9. package/dist/src/internal/accounts.js +15 -0
  10. package/dist/src/internal/accounts.js.map +1 -0
  11. package/dist/src/internal/chains.d.ts +11 -0
  12. package/dist/src/internal/chains.d.ts.map +1 -0
  13. package/dist/src/internal/chains.js +116 -0
  14. package/dist/src/internal/chains.js.map +1 -0
  15. package/dist/src/internal/clients.d.ts +10 -0
  16. package/dist/src/internal/clients.d.ts.map +1 -0
  17. package/dist/src/internal/clients.js +91 -0
  18. package/dist/src/internal/clients.js.map +1 -0
  19. package/dist/src/internal/contracts.d.ts +11 -0
  20. package/dist/src/internal/contracts.d.ts.map +1 -0
  21. package/dist/src/internal/contracts.js +141 -0
  22. package/dist/src/internal/contracts.js.map +1 -0
  23. package/dist/src/internal/hook-handlers/network.d.ts +4 -0
  24. package/dist/src/internal/hook-handlers/network.d.ts.map +1 -0
  25. package/dist/src/internal/hook-handlers/network.js +12 -0
  26. package/dist/src/internal/hook-handlers/network.js.map +1 -0
  27. package/dist/src/internal/initialization.d.ts +6 -0
  28. package/dist/src/internal/initialization.d.ts.map +1 -0
  29. package/dist/src/internal/initialization.js +14 -0
  30. package/dist/src/internal/initialization.js.map +1 -0
  31. package/dist/src/type-extensions.d.ts +8 -0
  32. package/dist/src/type-extensions.d.ts.map +1 -0
  33. package/dist/src/type-extensions.js +2 -0
  34. package/dist/src/type-extensions.js.map +1 -0
  35. package/dist/src/types.d.ts +166 -0
  36. package/dist/src/types.d.ts.map +1 -0
  37. package/dist/src/types.js +2 -0
  38. package/dist/src/types.js.map +1 -0
  39. package/package.json +46 -52
  40. package/src/index.ts +10 -39
  41. package/src/internal/accounts.ts +20 -7
  42. package/src/internal/chains.ts +122 -62
  43. package/src/internal/clients.ts +135 -141
  44. package/src/internal/contracts.ts +126 -150
  45. package/src/internal/hook-handlers/network.ts +27 -0
  46. package/src/internal/initialization.ts +67 -0
  47. package/src/type-extensions.ts +10 -0
  48. package/src/types.ts +237 -72
  49. package/.eslintrc.js +0 -24
  50. package/index.d.ts +0 -3
  51. package/index.d.ts.map +0 -1
  52. package/index.js +0 -20
  53. package/index.js.map +0 -1
  54. package/internal/accounts.d.ts +0 -5
  55. package/internal/accounts.d.ts.map +0 -1
  56. package/internal/accounts.js +0 -9
  57. package/internal/accounts.js.map +0 -1
  58. package/internal/bytecode.d.ts +0 -13
  59. package/internal/bytecode.d.ts.map +0 -1
  60. package/internal/bytecode.js +0 -94
  61. package/internal/bytecode.js.map +0 -1
  62. package/internal/chains.d.ts +0 -7
  63. package/internal/chains.d.ts.map +0 -1
  64. package/internal/chains.js +0 -80
  65. package/internal/chains.js.map +0 -1
  66. package/internal/clients.d.ts +0 -45
  67. package/internal/clients.d.ts.map +0 -1
  68. package/internal/clients.js +0 -136
  69. package/internal/clients.js.map +0 -1
  70. package/internal/contracts.d.ts +0 -11
  71. package/internal/contracts.d.ts.map +0 -1
  72. package/internal/contracts.js +0 -164
  73. package/internal/contracts.js.map +0 -1
  74. package/internal/errors.d.ts +0 -36
  75. package/internal/errors.d.ts.map +0 -1
  76. package/internal/errors.js +0 -102
  77. package/internal/errors.js.map +0 -1
  78. package/internal/tasks.d.ts +0 -2
  79. package/internal/tasks.d.ts.map +0 -1
  80. package/internal/tasks.js +0 -240
  81. package/internal/tasks.js.map +0 -1
  82. package/internal/type-extensions.d.ts +0 -19
  83. package/internal/type-extensions.d.ts.map +0 -1
  84. package/internal/type-extensions.js +0 -5
  85. package/internal/type-extensions.js.map +0 -1
  86. package/src/internal/bytecode.ts +0 -138
  87. package/src/internal/errors.ts +0 -125
  88. package/src/internal/tasks.ts +0 -341
  89. package/src/internal/type-extensions.ts +0 -27
  90. package/src/tsconfig.json +0 -15
  91. package/types.d.ts +0 -52
  92. package/types.d.ts.map +0 -1
  93. package/types.js +0 -3
  94. package/types.js.map +0 -1
@@ -1,9 +1,22 @@
1
- import type { EthereumProvider } from "hardhat/types";
2
- import type { Address } from "viem";
1
+ import type { EthereumProvider } from "hardhat/types/providers";
2
+ import type { Address as ViemAddress } from "viem";
3
3
 
4
- import memoize from "lodash.memoize";
4
+ const accountsCache = new WeakMap<EthereumProvider, ViemAddress[]>();
5
5
 
6
- export const getAccounts = memoize(
7
- async (provider: EthereumProvider): Promise<Address[]> =>
8
- provider.send("eth_accounts")
9
- );
6
+ export async function getAccounts(
7
+ provider: EthereumProvider,
8
+ ): Promise<ViemAddress[]> {
9
+ const cachedAccounts = accountsCache.get(provider);
10
+ if (cachedAccounts !== undefined) {
11
+ return cachedAccounts;
12
+ }
13
+
14
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
15
+ -- We know that the provider is going to return an array of accounts */
16
+ const accounts = (await provider.request({
17
+ method: "eth_accounts",
18
+ })) as ViemAddress[];
19
+ accountsCache.set(provider, accounts);
20
+
21
+ return accounts;
22
+ }
@@ -1,95 +1,155 @@
1
- import type { EthereumProvider } from "hardhat/types";
2
- import type { Chain } from "viem";
3
- import type { TestClientMode } from "../types";
4
-
5
- import memoize from "lodash.memoize";
1
+ import type { TestClientMode } from "../types.js";
2
+ import type { ChainType } from "hardhat/types/network";
3
+ import type { EthereumProvider } from "hardhat/types/providers";
4
+ import type { Chain as ViemChain } from "viem";
6
5
 
7
6
  import {
8
- UnknownDevelopmentNetworkError,
9
- NetworkNotFoundError,
10
- MultipleMatchingNetworksError,
11
- } from "./errors";
7
+ assertHardhatInvariant,
8
+ HardhatError,
9
+ } from "@nomicfoundation/hardhat-errors";
10
+ import { extractChain } from "viem";
11
+ import * as chainsModule from "viem/chains";
12
+ import { hardhat, anvil, optimism } from "viem/chains";
12
13
 
13
- export async function getChain(provider: EthereumProvider): Promise<Chain> {
14
- const chains: Record<string, Chain> = require("viem/chains");
15
- const chainId = await getChainId(provider);
14
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
15
+ -- TODO: this assertion should not be necessary */
16
+ const chains = Object.values(chainsModule) as ViemChain[];
16
17
 
17
- if (isDevelopmentNetwork(chainId)) {
18
- if (await isHardhatNetwork(provider)) {
19
- return chains.hardhat;
20
- } else if (await isFoundryNetwork(provider)) {
21
- return chains.foundry;
22
- } else {
23
- throw new UnknownDevelopmentNetworkError();
24
- }
18
+ const chainCache = new WeakMap<EthereumProvider, ViemChain>();
19
+ const chainIdCache = new WeakMap<EthereumProvider, number>();
20
+ const isHardhatNetworkCache = new WeakMap<EthereumProvider, boolean>();
21
+ const isAnvilNetworkCache = new WeakMap<EthereumProvider, boolean>();
22
+
23
+ const HARDHAT_METADATA_METHOD = "hardhat_metadata";
24
+ const ANVIL_NODE_INFO_METHOD = "anvil_nodeInfo";
25
+
26
+ export async function getChain(
27
+ provider: EthereumProvider,
28
+ chainType: ChainType | string,
29
+ ): Promise<ViemChain> {
30
+ const cachedChain = chainCache.get(provider);
31
+ if (cachedChain !== undefined) {
32
+ return cachedChain;
25
33
  }
26
34
 
27
- const matchingChains = Object.values(chains).filter(
28
- ({ id }) => id === chainId
29
- );
35
+ const chainId = await getChainId(provider);
36
+
37
+ let chain = extractChain({
38
+ chains,
39
+ id: chainId,
40
+ });
30
41
 
31
- if (matchingChains.length === 0) {
42
+ if ((await isDevelopmentNetwork(provider)) || chain === undefined) {
32
43
  if (await isHardhatNetwork(provider)) {
33
- return {
34
- ...chains.hardhat,
35
- id: chainId,
36
- };
37
- } else if (await isFoundryNetwork(provider)) {
38
- return {
39
- ...chains.foundry,
44
+ // TODO: We shoud improve how we handle the chains for the different chain
45
+ // types, as this is both a hardhat and an optimism chain.
46
+ //
47
+ // We are currently creating our chain based off optimism's, but that's
48
+ // not always the correct behavior, as the user may be connecting to
49
+ // a different chain.
50
+ if (chainType === "optimism") {
51
+ chain = { ...optimism, id: chainId };
52
+ } else {
53
+ chain = {
54
+ ...hardhat,
55
+ id: chainId,
56
+ };
57
+ }
58
+ } else if (await isAnvilNetwork(provider)) {
59
+ chain = {
60
+ ...anvil,
40
61
  id: chainId,
41
62
  };
63
+ } else if (chain === undefined) {
64
+ // If the chain couldn't be found and we can't detect the development
65
+ // network we throw an error.
66
+ throw new HardhatError(HardhatError.ERRORS.VIEM.NETWORK_NOT_FOUND, {
67
+ chainId,
68
+ });
42
69
  } else {
43
- throw new NetworkNotFoundError(chainId);
70
+ assertHardhatInvariant(
71
+ false,
72
+ "This should not happen, as we check in isDevelopmentNetwork that it's either hardhat or anvil",
73
+ );
44
74
  }
45
75
  }
46
76
 
47
- if (matchingChains.length > 1) {
48
- throw new MultipleMatchingNetworksError(chainId);
49
- }
77
+ chainCache.set(provider, chain);
50
78
 
51
- return matchingChains[0];
79
+ return chain;
52
80
  }
53
81
 
54
- export function isDevelopmentNetwork(chainId: number) {
55
- return chainId === 31337;
82
+ export async function getChainId(provider: EthereumProvider): Promise<number> {
83
+ const cachedChainId = chainIdCache.get(provider);
84
+ if (cachedChainId !== undefined) {
85
+ return cachedChainId;
86
+ }
87
+
88
+ const chainId = Number(await provider.request({ method: "eth_chainId" }));
89
+ chainIdCache.set(provider, chainId);
90
+
91
+ return chainId;
56
92
  }
57
93
 
58
- export async function getMode(
59
- provider: EthereumProvider
60
- ): Promise<TestClientMode> {
94
+ export async function isDevelopmentNetwork(
95
+ provider: EthereumProvider,
96
+ ): Promise<boolean> {
61
97
  if (await isHardhatNetwork(provider)) {
62
- return "hardhat";
63
- } else if (await isFoundryNetwork(provider)) {
64
- return "anvil";
65
- } else {
66
- throw new UnknownDevelopmentNetworkError();
98
+ return true;
99
+ }
100
+
101
+ if (await isAnvilNetwork(provider)) {
102
+ return true;
67
103
  }
104
+
105
+ return false;
68
106
  }
69
107
 
70
- const getChainId = memoize(async (provider: EthereumProvider) =>
71
- Number(await provider.send("eth_chainId"))
72
- );
108
+ export async function isHardhatNetwork(
109
+ provider: EthereumProvider,
110
+ ): Promise<boolean> {
111
+ const cachedIsHardhat = isHardhatNetworkCache.get(provider);
112
+ if (cachedIsHardhat !== undefined) {
113
+ return cachedIsHardhat;
114
+ }
115
+
116
+ const isHardhat = await isMethodSupported(provider, HARDHAT_METADATA_METHOD);
117
+ isHardhatNetworkCache.set(provider, isHardhat);
73
118
 
74
- const isHardhatNetwork = memoize(async (provider: EthereumProvider) =>
75
- detectNetworkByMethodName(provider, NetworkMethod.HARDHAT_METADATA)
76
- );
119
+ return isHardhat;
120
+ }
121
+
122
+ export async function isAnvilNetwork(
123
+ provider: EthereumProvider,
124
+ ): Promise<boolean> {
125
+ const cachedIsAnvil = isAnvilNetworkCache.get(provider);
126
+ if (cachedIsAnvil !== undefined) {
127
+ return cachedIsAnvil;
128
+ }
77
129
 
78
- const isFoundryNetwork = memoize(async (provider: EthereumProvider) =>
79
- detectNetworkByMethodName(provider, NetworkMethod.ANVIL_NODE_INFO)
80
- );
130
+ const isAnvil = await isMethodSupported(provider, ANVIL_NODE_INFO_METHOD);
131
+ isAnvilNetworkCache.set(provider, isAnvil);
81
132
 
82
- enum NetworkMethod {
83
- HARDHAT_METADATA = "hardhat_metadata",
84
- ANVIL_NODE_INFO = "anvil_nodeInfo",
133
+ return isAnvil;
85
134
  }
86
135
 
87
- async function detectNetworkByMethodName(
136
+ export async function getMode(
88
137
  provider: EthereumProvider,
89
- methodName: string
90
- ) {
138
+ ): Promise<TestClientMode> {
139
+ if (await isHardhatNetwork(provider)) {
140
+ return "hardhat";
141
+ }
142
+ if (await isAnvilNetwork(provider)) {
143
+ return "anvil";
144
+ }
145
+ throw new HardhatError(
146
+ HardhatError.ERRORS.VIEM.UNSUPPORTED_DEVELOPMENT_NETWORK,
147
+ );
148
+ }
149
+
150
+ async function isMethodSupported(provider: EthereumProvider, method: string) {
91
151
  try {
92
- await provider.send(methodName);
152
+ await provider.request({ method });
93
153
  return true;
94
154
  } catch {
95
155
  return false;
@@ -1,176 +1,170 @@
1
- import type { EthereumProvider } from "hardhat/types";
2
1
  import type {
3
- Address,
4
- Chain,
5
- PublicClientConfig,
6
- WalletClientConfig,
7
- TestClientConfig,
8
- } from "viem";
9
- import type {
10
- PublicClient,
2
+ GetPublicClientReturnType,
3
+ GetWalletClientReturnType,
11
4
  TestClient,
12
- TestClientMode,
13
- WalletClient,
14
- } from "../types";
15
-
16
- async function getParameters<TConfig extends {} | undefined>(
17
- chain: Chain,
18
- config: TConfig
19
- ) {
20
- const { isDevelopmentNetwork } = await import("./chains");
21
-
22
- const defaultParameters = isDevelopmentNetwork(chain.id)
23
- ? { pollingInterval: 50, cacheTime: 0 }
24
- : {};
5
+ } from "../types.js";
6
+ import type { ChainType } from "hardhat/types/network";
7
+ import type { EthereumProvider } from "hardhat/types/providers";
8
+ import type {
9
+ Address as ViemAddress,
10
+ PublicClientConfig as ViemPublicClientConfig,
11
+ TestClientConfig as ViemTestClientConfig,
12
+ WalletClientConfig as ViemWalletClientConfig,
13
+ } from "viem";
25
14
 
26
- const transportParameters = isDevelopmentNetwork(chain.id)
27
- ? { retryCount: 0 }
28
- : {};
15
+ import { HardhatError } from "@nomicfoundation/hardhat-errors";
16
+ import {
17
+ createPublicClient,
18
+ createWalletClient,
19
+ createTestClient,
20
+ custom as customTransport,
21
+ } from "viem";
22
+ import { publicActionsL2, walletActionsL2 } from "viem/op-stack";
29
23
 
30
- return {
31
- clientParameters: { ...defaultParameters, ...config },
32
- transportParameters,
33
- };
34
- }
24
+ import { getAccounts } from "./accounts.js";
25
+ import { getChain, getMode, isDevelopmentNetwork } from "./chains.js";
35
26
 
36
- /**
37
- * Get a PublicClient instance. This is a read-only client that can be used to
38
- * query the blockchain.
39
- *
40
- * @param provider The Ethereum provider used to connect to the blockchain.
41
- * @param publicClientConfig Optional configuration for the PublicClient instance. See the viem documentation for more information.
42
- * @returns A PublicClient instance.
43
- */
44
- export async function getPublicClient(
27
+ export async function getPublicClient<ChainTypeT extends ChainType | string>(
45
28
  provider: EthereumProvider,
46
- publicClientConfig?: Partial<PublicClientConfig>
47
- ): Promise<PublicClient> {
48
- const { getChain } = await import("./chains");
49
- const chain = publicClientConfig?.chain ?? (await getChain(provider));
50
- return innerGetPublicClient(provider, chain, publicClientConfig);
51
- }
52
-
53
- export async function innerGetPublicClient(
54
- provider: EthereumProvider,
55
- chain: Chain,
56
- publicClientConfig?: Partial<PublicClientConfig>
57
- ): Promise<PublicClient> {
58
- const viem = await import("viem");
59
- const { clientParameters, transportParameters } = await getParameters(
60
- chain,
61
- publicClientConfig
62
- );
29
+ chainType: ChainTypeT,
30
+ publicClientConfig?: Partial<ViemPublicClientConfig>,
31
+ ): Promise<GetPublicClientReturnType<ChainTypeT>> {
32
+ const chain =
33
+ publicClientConfig?.chain ?? (await getChain(provider, chainType));
34
+ const parameters = {
35
+ ...(await getDefaultClientParameters(provider)),
36
+ ...publicClientConfig,
37
+ };
63
38
 
64
- const publicClient = viem.createPublicClient({
39
+ let publicClient = createPublicClient({
65
40
  chain,
66
- transport: viem.custom(provider, transportParameters),
67
- ...clientParameters,
41
+ transport: customTransport(provider),
42
+ ...parameters,
68
43
  });
69
44
 
70
- return publicClient;
71
- }
45
+ if (chainType === "optimism") {
46
+ publicClient = publicClient.extend(publicActionsL2());
47
+ }
72
48
 
73
- /**
74
- * Get a list of WalletClient instances. These are read-write clients that can
75
- * be used to send transactions to the blockchain. Each client is associated
76
- * with an account obtained from the provider using `eth_accounts`.
77
- *
78
- * @param provider The Ethereum provider used to connect to the blockchain.
79
- * @param walletClientConfig Optional configuration for the WalletClient instances. See the viem documentation for more information.
80
- * @returns A list of WalletClient instances.
81
- */
82
- export async function getWalletClients(
83
- provider: EthereumProvider,
84
- walletClientConfig?: Partial<WalletClientConfig>
85
- ): Promise<WalletClient[]> {
86
- const { getAccounts } = await import("./accounts");
87
- const { getChain } = await import("./chains");
88
- const chain = walletClientConfig?.chain ?? (await getChain(provider));
89
- const accounts = await getAccounts(provider);
90
- return innerGetWalletClients(provider, chain, accounts, walletClientConfig);
49
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions --
50
+ We need to assert the type because TS gets confused with the conditional type */
51
+ return publicClient as GetPublicClientReturnType<ChainTypeT>;
91
52
  }
92
53
 
93
- export async function innerGetWalletClients(
54
+ export async function getWalletClients<ChainTypeT extends ChainType | string>(
94
55
  provider: EthereumProvider,
95
- chain: Chain,
96
- accounts: Address[],
97
- walletClientConfig?: Partial<WalletClientConfig>
98
- ): Promise<WalletClient[]> {
99
- const viem = await import("viem");
100
- const { clientParameters, transportParameters } = await getParameters(
101
- chain,
102
- walletClientConfig
103
- );
56
+ chainType: ChainTypeT,
57
+ walletClientConfig?: Partial<ViemWalletClientConfig>,
58
+ ): Promise<Array<GetWalletClientReturnType<ChainTypeT>>> {
59
+ const chain =
60
+ walletClientConfig?.chain ?? (await getChain(provider, chainType));
61
+ const accounts = await getAccounts(provider);
62
+ const parameters = {
63
+ ...(await getDefaultClientParameters(provider)),
64
+ ...walletClientConfig,
65
+ };
104
66
 
105
- const walletClients = accounts.map((account) =>
106
- viem.createWalletClient({
67
+ let walletClients = accounts.map((account) =>
68
+ createWalletClient({
107
69
  chain,
108
70
  account,
109
- transport: viem.custom(provider, transportParameters),
110
- ...clientParameters,
111
- })
71
+ transport: customTransport(provider),
72
+ ...parameters,
73
+ }),
112
74
  );
113
75
 
114
- return walletClients;
76
+ if (chainType === "optimism") {
77
+ walletClients = walletClients.map((walletClient) =>
78
+ walletClient.extend(walletActionsL2()),
79
+ );
80
+ }
81
+
82
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions --
83
+ We need to assert the type because TS gets confused with the conditional type */
84
+ return walletClients as Array<GetWalletClientReturnType<ChainTypeT>>;
115
85
  }
116
86
 
117
- /**
118
- * Get a WalletClient instance for a specific address. This is a read-write
119
- * client that can be used to send transactions to the blockchain.
120
- *
121
- * @param provider The Ethereum provider used to connect to the blockchain.
122
- * @param address The public address of the account to use.
123
- * @param walletClientConfig Optional configuration for the WalletClient instance. See the viem documentation for more information.
124
- * @returns A WalletClient instance.
125
- */
126
- export async function getWalletClient(
87
+ export async function getWalletClient<ChainTypeT extends ChainType | string>(
127
88
  provider: EthereumProvider,
128
- address: Address,
129
- walletClientConfig?: Partial<WalletClientConfig>
130
- ): Promise<WalletClient> {
131
- const { getChain } = await import("./chains");
132
- const chain = walletClientConfig?.chain ?? (await getChain(provider));
133
- return (
134
- await innerGetWalletClients(provider, chain, [address], walletClientConfig)
135
- )[0];
89
+ chainType: ChainTypeT,
90
+ address: ViemAddress,
91
+ walletClientConfig?: Partial<ViemWalletClientConfig>,
92
+ ): Promise<GetWalletClientReturnType<ChainTypeT>> {
93
+ const chain =
94
+ walletClientConfig?.chain ?? (await getChain(provider, chainType));
95
+ const parameters = {
96
+ ...(await getDefaultClientParameters(provider)),
97
+ ...walletClientConfig,
98
+ };
99
+
100
+ let walletClient = createWalletClient({
101
+ chain,
102
+ account: address,
103
+ transport: customTransport(provider),
104
+ ...parameters,
105
+ });
106
+
107
+ if (chainType === "optimism") {
108
+ walletClient = walletClient.extend(walletActionsL2());
109
+ }
110
+
111
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions --
112
+ We need to assert the type because TS gets confused with the conditional type */
113
+ return walletClient as GetWalletClientReturnType<ChainTypeT>;
136
114
  }
137
115
 
138
- /**
139
- * Get a TestClient instance. This is a read-write client that can be used to
140
- * perform actions only available on test nodes such as hardhat or anvil.
141
- *
142
- * @param provider The Ethereum provider used to connect to the blockchain.
143
- * @param testClientConfig Optional configuration for the TestClient instance. See the viem documentation for more information.
144
- * @returns A TestClient instance.
145
- */
146
- export async function getTestClient(
116
+ export async function getDefaultWalletClient<
117
+ ChainTypeT extends ChainType | string,
118
+ >(
147
119
  provider: EthereumProvider,
148
- testClientConfig?: Partial<TestClientConfig>
149
- ): Promise<TestClient> {
150
- const { getChain, getMode } = await import("./chains");
151
- const chain = testClientConfig?.chain ?? (await getChain(provider));
152
- const mode = await getMode(provider);
153
- return innerGetTestClient(provider, chain, mode, testClientConfig);
120
+ chainType: ChainTypeT,
121
+ walletClientConfig?: Partial<ViemWalletClientConfig>,
122
+ ): Promise<GetWalletClientReturnType<ChainTypeT>> {
123
+ const chain =
124
+ walletClientConfig?.chain ?? (await getChain(provider, chainType));
125
+ const [defaultAccount] = await getAccounts(provider);
126
+
127
+ if (defaultAccount === undefined) {
128
+ throw new HardhatError(
129
+ HardhatError.ERRORS.VIEM.DEFAULT_WALLET_CLIENT_NOT_FOUND,
130
+ {
131
+ chainId: chain.id,
132
+ },
133
+ );
134
+ }
135
+
136
+ return getWalletClient(
137
+ provider,
138
+ chainType,
139
+ defaultAccount,
140
+ walletClientConfig,
141
+ );
154
142
  }
155
143
 
156
- export async function innerGetTestClient(
144
+ export async function getTestClient<ChainTypeT extends ChainType | string>(
157
145
  provider: EthereumProvider,
158
- chain: Chain,
159
- mode: TestClientMode,
160
- testClientConfig?: Partial<TestClientConfig>
146
+ chainType: ChainTypeT,
147
+ testClientConfig?: Partial<ViemTestClientConfig>,
161
148
  ): Promise<TestClient> {
162
- const viem = await import("viem");
163
- const { clientParameters, transportParameters } = await getParameters(
164
- chain,
165
- testClientConfig
166
- );
149
+ const chain =
150
+ testClientConfig?.chain ?? (await getChain(provider, chainType));
151
+ const mode = await getMode(provider);
152
+ const parameters = { ...DEFAULT_CLIENT_PARAMETERS, ...testClientConfig };
167
153
 
168
- const testClient = viem.createTestClient({
169
- mode,
154
+ const testClient = createTestClient({
170
155
  chain,
171
- transport: viem.custom(provider, transportParameters),
172
- ...clientParameters,
156
+ mode,
157
+ transport: customTransport(provider),
158
+ ...parameters,
173
159
  });
174
160
 
175
161
  return testClient;
176
162
  }
163
+
164
+ const DEFAULT_CLIENT_PARAMETERS = { pollingInterval: 50, cacheTime: 0 };
165
+
166
+ async function getDefaultClientParameters(provider: EthereumProvider) {
167
+ return (await isDevelopmentNetwork(provider))
168
+ ? DEFAULT_CLIENT_PARAMETERS
169
+ : {};
170
+ }