@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,89 +1,65 @@
1
1
  import type {
2
- EthereumProvider,
3
- HardhatRuntimeEnvironment,
4
- } from "hardhat/types";
5
- import type { Abi, Address, Hex } from "viem";
6
- import type {
2
+ ContractReturnType,
7
3
  DeployContractConfig,
8
4
  GetContractAtConfig,
9
- GetContractReturnType,
10
5
  GetTransactionReturnType,
6
+ Libraries,
11
7
  PublicClient,
12
8
  SendDeploymentTransactionConfig,
13
9
  WalletClient,
14
- } from "../types";
10
+ } from "../types.js";
11
+ import type { PrefixedHexString } from "@nomicfoundation/hardhat-utils/hex";
12
+ import type { ArtifactManager } from "hardhat/types/artifacts";
13
+ import type { EthereumProvider } from "hardhat/types/providers";
14
+ import type { Abi as ViemAbi, Address as ViemAddress } from "viem";
15
15
 
16
- import { Libraries, resolveBytecodeWithLinkedLibraries } from "./bytecode";
17
- import { getPublicClient, getWalletClients } from "./clients";
18
- import {
19
- DefaultWalletClientNotFoundError,
20
- DeployContractError,
21
- HardhatViemError,
22
- InvalidConfirmationsError,
23
- } from "./errors";
16
+ import { HardhatError } from "@nomicfoundation/hardhat-errors";
17
+ import { toBigInt } from "@nomicfoundation/hardhat-utils/bigint";
18
+ import { resolveLinkedBytecode } from "@nomicfoundation/hardhat-utils/bytecode";
19
+ import { ensureError } from "@nomicfoundation/hardhat-utils/error";
20
+ import { getContractAddress, getContract } from "viem";
24
21
 
25
- async function getContractAbiAndBytecode(
26
- artifacts: HardhatRuntimeEnvironment["artifacts"],
27
- contractName: string,
28
- libraries: Libraries<Address>
29
- ) {
30
- const artifact = await artifacts.readArtifact(contractName);
31
- const bytecode = await resolveBytecodeWithLinkedLibraries(
32
- artifact,
33
- libraries
34
- );
22
+ import { getDefaultWalletClient, getPublicClient } from "./clients.js";
35
23
 
36
- return {
37
- abi: artifact.abi,
38
- bytecode,
39
- };
40
- }
41
-
42
- export async function deployContract(
43
- { artifacts, network }: HardhatRuntimeEnvironment,
44
- contractName: string,
45
- constructorArgs: any[] = [],
46
- config: DeployContractConfig = {}
47
- ): Promise<GetContractReturnType> {
24
+ export async function deployContract<ContractName extends string>(
25
+ provider: EthereumProvider,
26
+ artifactManager: ArtifactManager,
27
+ contractName: ContractName,
28
+ constructorArgs: unknown[] = [],
29
+ deployContractConfig: DeployContractConfig = {},
30
+ ): Promise<ContractReturnType<ContractName>> {
48
31
  const {
49
32
  client,
50
- confirmations,
33
+ confirmations = 1,
51
34
  libraries = {},
52
35
  ...deployContractParameters
53
- } = config;
36
+ } = deployContractConfig;
37
+
38
+ if (confirmations < 0) {
39
+ throw new HardhatError(HardhatError.ERRORS.VIEM.INVALID_CONFIRMATIONS, {
40
+ error: "Confirmations must be greather than 0.",
41
+ });
42
+ }
43
+ if (confirmations === 0) {
44
+ throw new HardhatError(HardhatError.ERRORS.VIEM.INVALID_CONFIRMATIONS, {
45
+ error:
46
+ "deployContract does not support 0 confirmations. Use sendDeploymentTransaction if you want to handle the deployment transaction yourself.",
47
+ });
48
+ }
49
+
54
50
  const [publicClient, walletClient, { abi, bytecode }] = await Promise.all([
55
- client?.public ?? getPublicClient(network.provider),
56
- client?.wallet ?? getDefaultWalletClient(network.provider, network.name),
57
- getContractAbiAndBytecode(artifacts, contractName, libraries),
51
+ client?.public ?? getPublicClient(provider, "l1"),
52
+ client?.wallet ?? getDefaultWalletClient(provider, "l1"),
53
+ getContractAbiAndBytecode(artifactManager, contractName, libraries),
58
54
  ]);
59
55
 
60
- return innerDeployContract(
61
- publicClient,
62
- walletClient,
63
- abi,
64
- bytecode,
65
- constructorArgs,
66
- deployContractParameters,
67
- confirmations
68
- );
69
- }
70
-
71
- export async function innerDeployContract(
72
- publicClient: PublicClient,
73
- walletClient: WalletClient,
74
- contractAbi: Abi,
75
- contractBytecode: Hex,
76
- constructorArgs: any[],
77
- deployContractParameters: DeployContractConfig = {},
78
- confirmations: number = 1
79
- ): Promise<GetContractReturnType> {
80
- let deploymentTxHash: Hex;
56
+ let deploymentTxHash: PrefixedHexString;
81
57
  // If gasPrice is defined, then maxFeePerGas and maxPriorityFeePerGas
82
58
  // must be undefined because it's a legaxy tx.
83
59
  if (deployContractParameters.gasPrice !== undefined) {
84
60
  deploymentTxHash = await walletClient.deployContract({
85
- abi: contractAbi,
86
- bytecode: contractBytecode,
61
+ abi,
62
+ bytecode,
87
63
  args: constructorArgs,
88
64
  ...deployContractParameters,
89
65
  maxFeePerGas: undefined,
@@ -91,21 +67,14 @@ export async function innerDeployContract(
91
67
  });
92
68
  } else {
93
69
  deploymentTxHash = await walletClient.deployContract({
94
- abi: contractAbi,
95
- bytecode: contractBytecode,
70
+ abi,
71
+ bytecode,
96
72
  args: constructorArgs,
97
73
  ...deployContractParameters,
98
74
  gasPrice: undefined,
99
75
  });
100
76
  }
101
77
 
102
- if (confirmations < 0) {
103
- throw new HardhatViemError("Confirmations must be greater than 0.");
104
- }
105
- if (confirmations === 0) {
106
- throw new InvalidConfirmationsError();
107
- }
108
-
109
78
  const { contractAddress } = await publicClient.waitForTransactionReceipt({
110
79
  hash: deploymentTxHash,
111
80
  confirmations,
@@ -115,63 +84,51 @@ export async function innerDeployContract(
115
84
  const transaction = await publicClient.getTransaction({
116
85
  hash: deploymentTxHash,
117
86
  });
118
- throw new DeployContractError(deploymentTxHash, transaction.blockNumber);
87
+ throw new HardhatError(HardhatError.ERRORS.VIEM.DEPLOY_CONTRACT_ERROR, {
88
+ txHash: deploymentTxHash,
89
+ blockNumber: transaction.blockNumber,
90
+ });
119
91
  }
120
92
 
121
- const contract = await innerGetContractAt(
93
+ const contract = createContractInstance(
94
+ contractName,
122
95
  publicClient,
123
96
  walletClient,
124
- contractAbi,
125
- contractAddress
97
+ abi,
98
+ contractAddress,
126
99
  );
127
100
 
128
101
  return contract;
129
102
  }
130
103
 
131
- export async function sendDeploymentTransaction(
132
- { artifacts, network }: HardhatRuntimeEnvironment,
133
- contractName: string,
134
- constructorArgs: any[] = [],
135
- config: SendDeploymentTransactionConfig = {}
104
+ export async function sendDeploymentTransaction<ContractName extends string>(
105
+ provider: EthereumProvider,
106
+ artifactManager: ArtifactManager,
107
+ contractName: ContractName,
108
+ constructorArgs: unknown[] = [],
109
+ sendDeploymentTransactionConfig: SendDeploymentTransactionConfig = {},
136
110
  ): Promise<{
137
- contract: GetContractReturnType;
111
+ contract: ContractReturnType<ContractName>;
138
112
  deploymentTransaction: GetTransactionReturnType;
139
113
  }> {
140
- const { client, libraries = {}, ...deployContractParameters } = config;
114
+ const {
115
+ client,
116
+ libraries = {},
117
+ ...deployContractParameters
118
+ } = sendDeploymentTransactionConfig;
141
119
  const [publicClient, walletClient, { abi, bytecode }] = await Promise.all([
142
- client?.public ?? getPublicClient(network.provider),
143
- client?.wallet ?? getDefaultWalletClient(network.provider, network.name),
144
- getContractAbiAndBytecode(artifacts, contractName, libraries),
120
+ client?.public ?? getPublicClient(provider, "l1"),
121
+ client?.wallet ?? getDefaultWalletClient(provider, "l1"),
122
+ getContractAbiAndBytecode(artifactManager, contractName, libraries),
145
123
  ]);
146
124
 
147
- return innerSendDeploymentTransaction(
148
- publicClient,
149
- walletClient,
150
- abi,
151
- bytecode,
152
- constructorArgs,
153
- deployContractParameters
154
- );
155
- }
156
-
157
- async function innerSendDeploymentTransaction(
158
- publicClient: PublicClient,
159
- walletClient: WalletClient,
160
- contractAbi: Abi,
161
- contractBytecode: Hex,
162
- constructorArgs: any[],
163
- deployContractParameters: SendDeploymentTransactionConfig = {}
164
- ): Promise<{
165
- contract: GetContractReturnType;
166
- deploymentTransaction: GetTransactionReturnType;
167
- }> {
168
- let deploymentTxHash: Hex;
125
+ let deploymentTxHash: PrefixedHexString;
169
126
  // If gasPrice is defined, then maxFeePerGas and maxPriorityFeePerGas
170
127
  // must be undefined because it's a legaxy tx.
171
128
  if (deployContractParameters.gasPrice !== undefined) {
172
129
  deploymentTxHash = await walletClient.deployContract({
173
- abi: contractAbi,
174
- bytecode: contractBytecode,
130
+ abi,
131
+ bytecode,
175
132
  args: constructorArgs,
176
133
  ...deployContractParameters,
177
134
  maxFeePerGas: undefined,
@@ -179,8 +136,8 @@ async function innerSendDeploymentTransaction(
179
136
  });
180
137
  } else {
181
138
  deploymentTxHash = await walletClient.deployContract({
182
- abi: contractAbi,
183
- bytecode: contractBytecode,
139
+ abi,
140
+ bytecode,
184
141
  args: constructorArgs,
185
142
  ...deployContractParameters,
186
143
  gasPrice: undefined,
@@ -191,71 +148,90 @@ async function innerSendDeploymentTransaction(
191
148
  hash: deploymentTxHash,
192
149
  });
193
150
 
194
- const { getContractAddress } = await import("viem");
195
151
  const contractAddress = getContractAddress({
196
152
  from: walletClient.account.address,
197
- nonce: BigInt(deploymentTx.nonce),
153
+ nonce: toBigInt(deploymentTx.nonce),
198
154
  });
199
155
 
200
- const contract = await innerGetContractAt(
156
+ const contract = createContractInstance(
157
+ contractName,
201
158
  publicClient,
202
159
  walletClient,
203
- contractAbi,
204
- contractAddress
160
+ abi,
161
+ contractAddress,
205
162
  );
206
163
 
207
164
  return { contract, deploymentTransaction: deploymentTx };
208
165
  }
209
166
 
210
- export async function getContractAt(
211
- { artifacts, network }: HardhatRuntimeEnvironment,
212
- contractName: string,
213
- address: Address,
214
- config: GetContractAtConfig = {}
215
- ): Promise<GetContractReturnType> {
216
- const [publicClient, walletClient, contractArtifact] = await Promise.all([
217
- config.client?.public ?? getPublicClient(network.provider),
218
- config.client?.wallet ??
219
- getDefaultWalletClient(network.provider, network.name),
220
- artifacts.readArtifact(contractName),
167
+ export async function getContractAt<ContractName extends string>(
168
+ provider: EthereumProvider,
169
+ artifactManager: ArtifactManager,
170
+ contractName: ContractName,
171
+ address: ViemAddress,
172
+ getContractAtConfig: GetContractAtConfig = {},
173
+ ): Promise<ContractReturnType<ContractName>> {
174
+ const [publicClient, walletClient, artifact] = await Promise.all([
175
+ getContractAtConfig.client?.public ?? getPublicClient(provider, "l1"),
176
+ getContractAtConfig.client?.wallet ??
177
+ getDefaultWalletClient(provider, "l1"),
178
+ artifactManager.readArtifact(contractName),
221
179
  ]);
222
180
 
223
- return innerGetContractAt(
181
+ return createContractInstance(
182
+ contractName,
224
183
  publicClient,
225
184
  walletClient,
226
- contractArtifact.abi,
227
- address
185
+ artifact.abi,
186
+ address,
228
187
  );
229
188
  }
230
189
 
231
- async function innerGetContractAt(
190
+ function createContractInstance<ContractName extends string>(
191
+ _contractName: ContractName,
232
192
  publicClient: PublicClient,
233
193
  walletClient: WalletClient,
234
- contractAbi: Abi,
235
- address: Address
236
- ): Promise<GetContractReturnType> {
237
- const viem = await import("viem");
238
- const contract = viem.getContract({
194
+ abi: ViemAbi,
195
+ address: ViemAddress,
196
+ ): ContractReturnType<ContractName> {
197
+ const contract = getContract({
239
198
  address,
240
199
  client: {
241
200
  public: publicClient,
242
201
  wallet: walletClient,
243
202
  },
244
- abi: contractAbi,
203
+ abi,
245
204
  });
246
205
 
247
- return contract;
206
+ /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
207
+ -- Cast it as TS can't infer the type of the contract */
208
+ return contract as ContractReturnType<ContractName>;
248
209
  }
249
210
 
250
- async function getDefaultWalletClient(
251
- provider: EthereumProvider,
252
- networkName: string
253
- ): Promise<WalletClient> {
254
- const [defaultWalletClient] = await getWalletClients(provider);
255
-
256
- if (defaultWalletClient === undefined) {
257
- throw new DefaultWalletClientNotFoundError(networkName);
211
+ async function getContractAbiAndBytecode(
212
+ artifacts: ArtifactManager,
213
+ contractName: string,
214
+ libraries: Libraries,
215
+ ) {
216
+ const artifact = await artifacts.readArtifact(contractName);
217
+ let bytecode;
218
+ try {
219
+ bytecode = resolveLinkedBytecode(artifact, libraries);
220
+ } catch (error) {
221
+ ensureError(error);
222
+
223
+ throw new HardhatError(
224
+ HardhatError.ERRORS.VIEM.LINKING_CONTRACT_ERROR,
225
+ {
226
+ contractName,
227
+ error: error.message,
228
+ },
229
+ error,
230
+ );
258
231
  }
259
232
 
260
- return defaultWalletClient;
233
+ return {
234
+ abi: artifact.abi,
235
+ bytecode,
236
+ };
261
237
  }
@@ -0,0 +1,27 @@
1
+ import type { HookContext, NetworkHooks } from "hardhat/types/hooks";
2
+ import type { ChainType, NetworkConnection } from "hardhat/types/network";
3
+
4
+ import { initializeViem } from "../initialization.js";
5
+
6
+ export default async (): Promise<Partial<NetworkHooks>> => {
7
+ const handlers: Partial<NetworkHooks> = {
8
+ async newConnection<ChainTypeT extends ChainType | string>(
9
+ context: HookContext,
10
+ next: (
11
+ nextContext: HookContext,
12
+ ) => Promise<NetworkConnection<ChainTypeT>>,
13
+ ) {
14
+ const connection: NetworkConnection<ChainTypeT> = await next(context);
15
+
16
+ connection.viem = initializeViem(
17
+ connection.chainType,
18
+ connection.provider,
19
+ context.artifacts,
20
+ );
21
+
22
+ return connection;
23
+ },
24
+ };
25
+
26
+ return handlers;
27
+ };
@@ -0,0 +1,67 @@
1
+ import type { HardhatViemHelpers } from "../types.js";
2
+ import type { ArtifactManager } from "hardhat/types/artifacts";
3
+ import type { ChainType } from "hardhat/types/network";
4
+ import type { EthereumProvider } from "hardhat/types/providers";
5
+
6
+ import {
7
+ getPublicClient,
8
+ getWalletClients,
9
+ getWalletClient,
10
+ getTestClient,
11
+ } from "./clients.js";
12
+ import {
13
+ deployContract,
14
+ getContractAt,
15
+ sendDeploymentTransaction,
16
+ } from "./contracts.js";
17
+
18
+ export function initializeViem<ChainTypeT extends ChainType | string>(
19
+ chainType: ChainTypeT,
20
+ provider: EthereumProvider,
21
+ artifactManager: ArtifactManager,
22
+ ): HardhatViemHelpers<ChainTypeT> {
23
+ return {
24
+ getPublicClient: (publicClientConfig) =>
25
+ getPublicClient(provider, chainType, publicClientConfig),
26
+
27
+ getWalletClients: (walletClientConfig) =>
28
+ getWalletClients(provider, chainType, walletClientConfig),
29
+
30
+ getWalletClient: (address, walletClientConfig) =>
31
+ getWalletClient(provider, chainType, address, walletClientConfig),
32
+
33
+ getTestClient: (testClientConfig) =>
34
+ getTestClient(provider, chainType, testClientConfig),
35
+
36
+ deployContract: (contractName, constructorArgs, deployContractConfig) =>
37
+ deployContract(
38
+ provider,
39
+ artifactManager,
40
+ contractName,
41
+ constructorArgs,
42
+ deployContractConfig,
43
+ ),
44
+
45
+ sendDeploymentTransaction: (
46
+ contractName,
47
+ constructorArgs,
48
+ sendDeploymentTransactionConfig,
49
+ ) =>
50
+ sendDeploymentTransaction(
51
+ provider,
52
+ artifactManager,
53
+ contractName,
54
+ constructorArgs,
55
+ sendDeploymentTransactionConfig,
56
+ ),
57
+
58
+ getContractAt: (contractName, address, getContractAtConfig) =>
59
+ getContractAt(
60
+ provider,
61
+ artifactManager,
62
+ contractName,
63
+ address,
64
+ getContractAtConfig,
65
+ ),
66
+ };
67
+ }
@@ -0,0 +1,10 @@
1
+ import type { HardhatViemHelpers } from "./types.js";
2
+
3
+ import "hardhat/types/network";
4
+ declare module "hardhat/types/network" {
5
+ interface NetworkConnection<
6
+ ChainTypeT extends ChainType | string = DefaultChainType,
7
+ > {
8
+ viem: HardhatViemHelpers<ChainTypeT>;
9
+ }
10
+ }