hardhat 3.0.6 → 3.0.8

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 (127) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/solidity.d.ts.map +1 -1
  3. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/solidity.js +1 -2
  4. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/solidity.js.map +1 -1
  5. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-provider.d.ts +1 -0
  6. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-provider.d.ts.map +1 -1
  7. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-provider.js +9 -2
  8. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-provider.js.map +1 -1
  9. package/dist/src/internal/builtin-plugins/network-manager/hook-handlers/hre.d.ts.map +1 -1
  10. package/dist/src/internal/builtin-plugins/network-manager/hook-handlers/hre.js +13 -5
  11. package/dist/src/internal/builtin-plugins/network-manager/hook-handlers/hre.js.map +1 -1
  12. package/dist/src/internal/builtin-plugins/network-manager/hook-handlers/network.js +1 -1
  13. package/dist/src/internal/builtin-plugins/network-manager/hook-handlers/network.js.map +1 -1
  14. package/dist/src/internal/builtin-plugins/network-manager/network-manager.d.ts +4 -3
  15. package/dist/src/internal/builtin-plugins/network-manager/network-manager.d.ts.map +1 -1
  16. package/dist/src/internal/builtin-plugins/network-manager/network-manager.js +79 -37
  17. package/dist/src/internal/builtin-plugins/network-manager/network-manager.js.map +1 -1
  18. package/dist/src/internal/builtin-plugins/network-manager/type-validation.js +3 -3
  19. package/dist/src/internal/builtin-plugins/network-manager/type-validation.js.map +1 -1
  20. package/dist/src/internal/builtin-plugins/node/artifacts/build-info-watcher.d.ts +25 -0
  21. package/dist/src/internal/builtin-plugins/node/artifacts/build-info-watcher.d.ts.map +1 -0
  22. package/dist/src/internal/builtin-plugins/node/artifacts/build-info-watcher.js +56 -0
  23. package/dist/src/internal/builtin-plugins/node/artifacts/build-info-watcher.js.map +1 -0
  24. package/dist/src/internal/builtin-plugins/node/helpers.d.ts +12 -0
  25. package/dist/src/internal/builtin-plugins/node/helpers.d.ts.map +1 -1
  26. package/dist/src/internal/builtin-plugins/node/helpers.js +32 -0
  27. package/dist/src/internal/builtin-plugins/node/helpers.js.map +1 -1
  28. package/dist/src/internal/builtin-plugins/node/json-rpc/server.d.ts +3 -10
  29. package/dist/src/internal/builtin-plugins/node/json-rpc/server.d.ts.map +1 -1
  30. package/dist/src/internal/builtin-plugins/node/json-rpc/server.js +1 -1
  31. package/dist/src/internal/builtin-plugins/node/json-rpc/server.js.map +1 -1
  32. package/dist/src/internal/builtin-plugins/node/task-action.d.ts.map +1 -1
  33. package/dist/src/internal/builtin-plugins/node/task-action.js +14 -4
  34. package/dist/src/internal/builtin-plugins/node/task-action.js.map +1 -1
  35. package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.d.ts +13 -5
  36. package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.d.ts.map +1 -1
  37. package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.js +126 -58
  38. package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.js.map +1 -1
  39. package/dist/src/internal/builtin-plugins/solidity/build-system/cache.d.ts +1 -1
  40. package/dist/src/internal/builtin-plugins/solidity/build-system/cache.d.ts.map +1 -1
  41. package/dist/src/internal/builtin-plugins/solidity/hook-handlers/hre.d.ts.map +1 -1
  42. package/dist/src/internal/builtin-plugins/solidity/hook-handlers/hre.js +14 -6
  43. package/dist/src/internal/builtin-plugins/solidity/hook-handlers/hre.js.map +1 -1
  44. package/dist/src/internal/builtin-plugins/solidity/index.d.ts.map +1 -1
  45. package/dist/src/internal/builtin-plugins/solidity/index.js +8 -0
  46. package/dist/src/internal/builtin-plugins/solidity/index.js.map +1 -1
  47. package/dist/src/internal/builtin-plugins/solidity/tasks/build.d.ts +4 -2
  48. package/dist/src/internal/builtin-plugins/solidity/tasks/build.d.ts.map +1 -1
  49. package/dist/src/internal/builtin-plugins/solidity/tasks/build.js +37 -10
  50. package/dist/src/internal/builtin-plugins/solidity/tasks/build.js.map +1 -1
  51. package/dist/src/internal/builtin-plugins/solidity-test/config.d.ts +4 -2
  52. package/dist/src/internal/builtin-plugins/solidity-test/config.d.ts.map +1 -1
  53. package/dist/src/internal/builtin-plugins/solidity-test/config.js +24 -4
  54. package/dist/src/internal/builtin-plugins/solidity-test/config.js.map +1 -1
  55. package/dist/src/internal/builtin-plugins/solidity-test/helpers.d.ts +1 -1
  56. package/dist/src/internal/builtin-plugins/solidity-test/helpers.d.ts.map +1 -1
  57. package/dist/src/internal/builtin-plugins/solidity-test/helpers.js +12 -3
  58. package/dist/src/internal/builtin-plugins/solidity-test/helpers.js.map +1 -1
  59. package/dist/src/internal/builtin-plugins/solidity-test/hook-handlers/config.d.ts.map +1 -1
  60. package/dist/src/internal/builtin-plugins/solidity-test/hook-handlers/config.js +1 -1
  61. package/dist/src/internal/builtin-plugins/solidity-test/hook-handlers/config.js.map +1 -1
  62. package/dist/src/internal/builtin-plugins/solidity-test/task-action.d.ts.map +1 -1
  63. package/dist/src/internal/builtin-plugins/solidity-test/task-action.js +16 -39
  64. package/dist/src/internal/builtin-plugins/solidity-test/task-action.js.map +1 -1
  65. package/dist/src/internal/builtin-plugins/solidity-test/type-extensions.d.ts +17 -7
  66. package/dist/src/internal/builtin-plugins/solidity-test/type-extensions.d.ts.map +1 -1
  67. package/dist/src/internal/core/hook-manager.d.ts.map +1 -1
  68. package/dist/src/internal/core/hook-manager.js +3 -1
  69. package/dist/src/internal/core/hook-manager.js.map +1 -1
  70. package/dist/src/internal/core/hre.d.ts +29 -1
  71. package/dist/src/internal/core/hre.d.ts.map +1 -1
  72. package/dist/src/internal/core/hre.js +57 -20
  73. package/dist/src/internal/core/hre.js.map +1 -1
  74. package/dist/src/internal/core/plugins/detect-plugin-npm-dependency-problems.d.ts +2 -1
  75. package/dist/src/internal/core/plugins/detect-plugin-npm-dependency-problems.d.ts.map +1 -1
  76. package/dist/src/internal/core/plugins/detect-plugin-npm-dependency-problems.js +5 -4
  77. package/dist/src/internal/core/plugins/detect-plugin-npm-dependency-problems.js.map +1 -1
  78. package/dist/src/internal/core/plugins/resolve-plugin-list.js +41 -4
  79. package/dist/src/internal/core/plugins/resolve-plugin-list.js.map +1 -1
  80. package/dist/src/internal/core/tasks/resolved-task.d.ts.map +1 -1
  81. package/dist/src/internal/core/tasks/resolved-task.js +1 -1
  82. package/dist/src/internal/core/tasks/resolved-task.js.map +1 -1
  83. package/dist/src/internal/utils/package.d.ts +1 -0
  84. package/dist/src/internal/utils/package.d.ts.map +1 -1
  85. package/dist/src/internal/utils/package.js +17 -1
  86. package/dist/src/internal/utils/package.js.map +1 -1
  87. package/dist/src/types/hre.d.ts +4 -0
  88. package/dist/src/types/hre.d.ts.map +1 -1
  89. package/dist/src/types/network.d.ts +40 -0
  90. package/dist/src/types/network.d.ts.map +1 -1
  91. package/dist/src/types/plugins.d.ts +8 -0
  92. package/dist/src/types/plugins.d.ts.map +1 -1
  93. package/dist/src/types/solidity/build-system.d.ts +23 -8
  94. package/dist/src/types/solidity/build-system.d.ts.map +1 -1
  95. package/package.json +5 -4
  96. package/src/internal/builtin-plugins/coverage/hook-handlers/solidity.ts +2 -3
  97. package/src/internal/builtin-plugins/network-manager/edr/edr-provider.ts +20 -1
  98. package/src/internal/builtin-plugins/network-manager/hook-handlers/hre.ts +36 -18
  99. package/src/internal/builtin-plugins/network-manager/hook-handlers/network.ts +1 -1
  100. package/src/internal/builtin-plugins/network-manager/network-manager.ts +137 -60
  101. package/src/internal/builtin-plugins/network-manager/type-validation.ts +3 -3
  102. package/src/internal/builtin-plugins/node/artifacts/build-info-watcher.ts +82 -0
  103. package/src/internal/builtin-plugins/node/helpers.ts +64 -0
  104. package/src/internal/builtin-plugins/node/json-rpc/server.ts +3 -10
  105. package/src/internal/builtin-plugins/node/task-action.ts +31 -5
  106. package/src/internal/builtin-plugins/solidity/build-system/build-system.ts +203 -98
  107. package/src/internal/builtin-plugins/solidity/build-system/cache.ts +1 -1
  108. package/src/internal/builtin-plugins/solidity/hook-handlers/hre.ts +22 -5
  109. package/src/internal/builtin-plugins/solidity/index.ts +8 -0
  110. package/src/internal/builtin-plugins/solidity/tasks/build.ts +59 -16
  111. package/src/internal/builtin-plugins/solidity-test/config.ts +46 -3
  112. package/src/internal/builtin-plugins/solidity-test/helpers.ts +17 -4
  113. package/src/internal/builtin-plugins/solidity-test/hook-handlers/config.ts +5 -1
  114. package/src/internal/builtin-plugins/solidity-test/task-action.ts +21 -48
  115. package/src/internal/builtin-plugins/solidity-test/type-extensions.ts +23 -9
  116. package/src/internal/core/hook-manager.ts +9 -1
  117. package/src/internal/core/hre.ts +102 -32
  118. package/src/internal/core/plugins/detect-plugin-npm-dependency-problems.ts +5 -0
  119. package/src/internal/core/plugins/resolve-plugin-list.ts +58 -4
  120. package/src/internal/core/tasks/resolved-task.ts +1 -0
  121. package/src/internal/utils/package.ts +31 -1
  122. package/src/types/hre.ts +4 -0
  123. package/src/types/network.ts +45 -0
  124. package/src/types/plugins.ts +5 -0
  125. package/src/types/solidity/build-system.ts +23 -7
  126. package/templates/hardhat-3/01-node-test-runner-viem/package.json +3 -3
  127. package/templates/hardhat-3/02-mocha-ethers/package.json +5 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hardhat",
3
- "version": "3.0.6",
3
+ "version": "3.0.8",
4
4
  "description": "Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.",
5
5
  "homepage": "https://github.com/nomicfoundation/hardhat/tree/v-next/v-next/hardhat",
6
6
  "repository": {
@@ -70,14 +70,15 @@
70
70
  "@nomicfoundation/hardhat-test-utils": "^2.0.1"
71
71
  },
72
72
  "dependencies": {
73
- "@nomicfoundation/edr": "0.12.0-next.5",
74
- "@nomicfoundation/hardhat-errors": "^3.0.2",
75
- "@nomicfoundation/hardhat-utils": "^3.0.2",
73
+ "@nomicfoundation/edr": "0.12.0-next.7",
74
+ "@nomicfoundation/hardhat-errors": "^3.0.3",
75
+ "@nomicfoundation/hardhat-utils": "^3.0.3",
76
76
  "@nomicfoundation/hardhat-zod-utils": "^3.0.1",
77
77
  "@nomicfoundation/solidity-analyzer": "^0.1.1",
78
78
  "@sentry/core": "^9.4.0",
79
79
  "adm-zip": "^0.4.16",
80
80
  "chalk": "^5.3.0",
81
+ "chokidar": "^4.0.3",
81
82
  "debug": "^4.3.2",
82
83
  "enquirer": "^2.3.0",
83
84
  "ethereum-cryptography": "^2.2.1",
@@ -30,9 +30,8 @@ export default async (): Promise<Partial<SolidityHooks>> => ({
30
30
  ) => {
31
31
  // NOTE: We do not want to instrument the test project files as we don't
32
32
  // want to report coverage for them.
33
- const isTestSource =
34
- fsPath.startsWith(context.config.paths.tests.solidity) ||
35
- fsPath.endsWith(".t.sol");
33
+
34
+ const isTestSource = (await context.solidity.getScope(fsPath)) === "tests";
36
35
 
37
36
  if (context.globalOptions.coverage && !isTestSource) {
38
37
  try {
@@ -30,6 +30,7 @@ import {
30
30
  opHardforkFromString,
31
31
  l1GenesisState,
32
32
  l1HardforkFromString,
33
+ ContractDecoder,
33
34
  } from "@nomicfoundation/edr";
34
35
  import {
35
36
  assertHardhatInvariant,
@@ -174,6 +175,8 @@ export class EdrProvider extends BaseProvider {
174
175
  // We need to catch errors here, as the provider creation can panic unexpectedly,
175
176
  // and we want to make sure such a crash is propagated as a ProviderError.
176
177
  try {
178
+ const contractDecoder = ContractDecoder.withContracts(tracingConfig);
179
+
177
180
  const context = await getGlobalEdrContext();
178
181
  const provider = await context.createProvider(
179
182
  hardhatChainTypeToEdrChainType(networkConfig.chainType),
@@ -200,7 +203,7 @@ export class EdrProvider extends BaseProvider {
200
203
  edrProvider.onSubscriptionEvent(event);
201
204
  },
202
205
  },
203
- tracingConfig,
206
+ contractDecoder,
204
207
  );
205
208
 
206
209
  edrProvider = new EdrProvider(provider, jsonRpcRequestWrapper);
@@ -301,6 +304,22 @@ export class EdrProvider extends BaseProvider {
301
304
  this.#provider = undefined;
302
305
  }
303
306
 
307
+ public async addCompilationResult(
308
+ solcVersion: string,
309
+ compilerInput: any,
310
+ compilerOutput: any,
311
+ ): Promise<void> {
312
+ if (this.#provider === undefined) {
313
+ throw new HardhatError(HardhatError.ERRORS.CORE.NETWORK.PROVIDER_CLOSED);
314
+ }
315
+
316
+ await this.#provider.addCompilationResult(
317
+ solcVersion,
318
+ compilerInput,
319
+ compilerOutput,
320
+ );
321
+ }
322
+
304
323
  async #handleEdrResponse(
305
324
  edrResponse: Response,
306
325
  ): Promise<SuccessfulJsonRpcResponse> {
@@ -1,4 +1,8 @@
1
- import type { HardhatRuntimeEnvironmentHooks } from "../../../../types/hooks.js";
1
+ import type {
2
+ HardhatRuntimeEnvironmentHooks,
3
+ HookContext,
4
+ } from "../../../../types/hooks.js";
5
+ import type { HardhatRuntimeEnvironment } from "../../../../types/hre.js";
2
6
  import type { NetworkManager } from "../../../../types/network.js";
3
7
 
4
8
  import { DEFAULT_NETWORK_NAME } from "../../../constants.js";
@@ -7,30 +11,44 @@ export default async (): Promise<Partial<HardhatRuntimeEnvironmentHooks>> => ({
7
11
  created: async (context, hre) => {
8
12
  let networkManager: NetworkManager | undefined;
9
13
 
10
- const userConfigNetworks = hre.userConfig.networks;
11
-
12
14
  hre.network = {
13
15
  async connect(networkConnectionParams) {
14
- const { NetworkManagerImplementation } = await import(
15
- "../network-manager.js"
16
- );
17
-
18
16
  if (networkManager === undefined) {
19
- networkManager = new NetworkManagerImplementation(
20
- hre.globalOptions.network !== undefined
21
- ? hre.globalOptions.network
22
- : DEFAULT_NETWORK_NAME,
23
- hre.config.defaultChainType,
24
- hre.config.networks,
25
- context.hooks,
26
- context.artifacts,
27
- userConfigNetworks,
28
- hre.config.chainDescriptors,
29
- );
17
+ networkManager = await createNetworkManager(hre, context);
30
18
  }
31
19
 
32
20
  return networkManager.connect(networkConnectionParams);
33
21
  },
22
+ async createServer(...params) {
23
+ if (networkManager === undefined) {
24
+ networkManager = await createNetworkManager(hre, context);
25
+ }
26
+
27
+ return networkManager.createServer(...params);
28
+ },
34
29
  };
35
30
  },
36
31
  });
32
+
33
+ async function createNetworkManager(
34
+ hre: HardhatRuntimeEnvironment,
35
+ context: HookContext,
36
+ ): Promise<NetworkManager> {
37
+ const { NetworkManagerImplementation } = await import(
38
+ "../network-manager.js"
39
+ );
40
+
41
+ return new NetworkManagerImplementation(
42
+ hre.globalOptions.network !== undefined
43
+ ? hre.globalOptions.network
44
+ : DEFAULT_NETWORK_NAME,
45
+ hre.config.defaultChainType,
46
+ hre.config.networks,
47
+ context.hooks,
48
+ context.artifacts,
49
+ hre.userConfig,
50
+ hre.config.chainDescriptors,
51
+ hre.globalOptions.config,
52
+ hre.config.paths.root,
53
+ );
54
+ }
@@ -23,7 +23,7 @@ export default async (): Promise<Partial<NetworkHooks>> => {
23
23
  const requestHandlersPerConnection: WeakMap<
24
24
  NetworkConnection<ChainType | string>,
25
25
  RequestHandler[]
26
- > = new Map();
26
+ > = new WeakMap();
27
27
 
28
28
  const initializationMutex = new AsyncMutex();
29
29
 
@@ -2,36 +2,40 @@ import type { CoverageConfig } from "./edr/types/coverage.js";
2
2
  import type { ArtifactManager } from "../../../types/artifacts.js";
3
3
  import type {
4
4
  ChainDescriptorsConfig,
5
+ HardhatUserConfig,
5
6
  NetworkConfig,
6
7
  NetworkConfigOverride,
7
- NetworkUserConfig,
8
8
  } from "../../../types/config.js";
9
9
  import type { HookManager } from "../../../types/hooks.js";
10
10
  import type {
11
11
  ChainType,
12
12
  DefaultChainType,
13
+ JsonRpcServer,
13
14
  NetworkConnection,
14
15
  NetworkConnectionParams,
15
16
  NetworkManager,
16
17
  } from "../../../types/network.js";
18
+ import type { HardhatPlugin } from "../../../types/plugins.js";
17
19
  import type {
18
20
  EthereumProvider,
19
21
  JsonRpcRequest,
20
22
  JsonRpcResponse,
21
23
  } from "../../../types/providers.js";
22
24
 
23
- import { HardhatError } from "@nomicfoundation/hardhat-errors";
24
- import { readBinaryFile } from "@nomicfoundation/hardhat-utils/fs";
25
+ import {
26
+ HardhatError,
27
+ assertHardhatInvariant,
28
+ } from "@nomicfoundation/hardhat-errors";
29
+ import { exists, readBinaryFile } from "@nomicfoundation/hardhat-utils/fs";
25
30
  import { deepMerge } from "@nomicfoundation/hardhat-utils/lang";
26
31
 
27
- import { resolveConfigurationVariable } from "../../core/configuration-variables.js";
32
+ import { resolveUserConfigToHardhatConfig } from "../../core/hre.js";
28
33
  import { isSupportedChainType } from "../../edr/chain-type.js";
34
+ import { JsonRpcServerImplementation } from "../node/json-rpc/server.js";
29
35
 
30
- import { resolveEdrNetwork, resolveHttpNetwork } from "./config-resolution.js";
31
36
  import { EdrProvider } from "./edr/edr-provider.js";
32
37
  import { HttpProvider } from "./http-provider.js";
33
38
  import { NetworkConnectionImplementation } from "./network-connection.js";
34
- import { validateNetworkConfigOverride } from "./type-validation.js";
35
39
 
36
40
  export type JsonRpcRequestWrapperFunction = (
37
41
  request: JsonRpcRequest,
@@ -44,8 +48,10 @@ export class NetworkManagerImplementation implements NetworkManager {
44
48
  readonly #networkConfigs: Readonly<Record<string, Readonly<NetworkConfig>>>;
45
49
  readonly #hookManager: Readonly<HookManager>;
46
50
  readonly #artifactsManager: Readonly<ArtifactManager>;
47
- readonly #userConfigNetworks: Readonly<Record<string, NetworkUserConfig>>;
51
+ readonly #userConfig: Readonly<HardhatUserConfig>;
48
52
  readonly #chainDescriptors: Readonly<ChainDescriptorsConfig>;
53
+ readonly #userProvidedConfigPath: Readonly<string | undefined>;
54
+ readonly #projectRoot: string;
49
55
 
50
56
  #nextConnectionId = 0;
51
57
 
@@ -55,16 +61,20 @@ export class NetworkManagerImplementation implements NetworkManager {
55
61
  networkConfigs: Record<string, NetworkConfig>,
56
62
  hookManager: HookManager,
57
63
  artifactsManager: ArtifactManager,
58
- userConfigNetworks: Record<string, NetworkUserConfig> | undefined,
64
+ userConfig: HardhatUserConfig,
59
65
  chainDescriptors: ChainDescriptorsConfig,
66
+ userProvidedConfigPath: string | undefined,
67
+ projectRoot: string,
60
68
  ) {
61
69
  this.#defaultNetwork = defaultNetwork;
62
70
  this.#defaultChainType = defaultChainType;
63
71
  this.#networkConfigs = networkConfigs;
64
72
  this.#hookManager = hookManager;
65
73
  this.#artifactsManager = artifactsManager;
66
- this.#userConfigNetworks = userConfigNetworks ?? {};
74
+ this.#userConfig = userConfig;
67
75
  this.#chainDescriptors = chainDescriptors;
76
+ this.#userProvidedConfigPath = userProvidedConfigPath;
77
+ this.#projectRoot = projectRoot;
68
78
  }
69
79
 
70
80
  public async connect<
@@ -97,6 +107,23 @@ export class NetworkManagerImplementation implements NetworkManager {
97
107
  return networkConnection as NetworkConnection<ChainTypeT>;
98
108
  }
99
109
 
110
+ public async createServer(
111
+ networkOrParams: NetworkConnectionParams | string = "default",
112
+ _hostname?: string,
113
+ port?: number,
114
+ ): Promise<JsonRpcServer> {
115
+ const insideDocker = await exists("/.dockerenv");
116
+ const hostname = _hostname ?? (insideDocker ? "0.0.0.0" : "127.0.0.1");
117
+
118
+ const { provider } = await this.connect(networkOrParams);
119
+
120
+ return new JsonRpcServerImplementation({
121
+ hostname,
122
+ port,
123
+ provider,
124
+ });
125
+ }
126
+
100
127
  async #initializeNetworkConnection<ChainTypeT extends ChainType | string>(
101
128
  networkName?: string,
102
129
  chainType?: ChainTypeT,
@@ -113,57 +140,10 @@ export class NetworkManagerImplementation implements NetworkManager {
113
140
  );
114
141
  }
115
142
 
116
- let resolvedNetworkConfigOverride: NetworkConfig | undefined;
117
- if (networkConfigOverride !== undefined) {
118
- if (
119
- "type" in networkConfigOverride &&
120
- networkConfigOverride.type !==
121
- this.#networkConfigs[resolvedNetworkName].type
122
- ) {
123
- throw new HardhatError(
124
- HardhatError.ERRORS.CORE.NETWORK.INVALID_CONFIG_OVERRIDE,
125
- {
126
- errors: `\t* The type of the network cannot be changed.`,
127
- },
128
- );
129
- }
130
-
131
- const newConfig = deepMerge(
132
- this.#userConfigNetworks[resolvedNetworkName],
133
- networkConfigOverride,
134
- );
135
-
136
- // As normalizeNetworkConfigOverride is not type-safe, we validate the
137
- // normalized network config override immediately after normalizing it.
138
- const validationErrors = await validateNetworkConfigOverride(newConfig);
139
- if (validationErrors.length > 0) {
140
- throw new HardhatError(
141
- HardhatError.ERRORS.CORE.NETWORK.INVALID_CONFIG_OVERRIDE,
142
- {
143
- errors: `\t${validationErrors
144
- .map((error) =>
145
- error.path.length > 0
146
- ? `* Error in ${error.path.join(".")}: ${error.message}`
147
- : `* ${error.message}`,
148
- )
149
- .join("\n\t")}`,
150
- },
151
- );
152
- }
153
-
154
- resolvedNetworkConfigOverride =
155
- newConfig.type === "http"
156
- ? resolveHttpNetwork(newConfig, (strOrConfigVar) =>
157
- resolveConfigurationVariable(this.#hookManager, strOrConfigVar),
158
- )
159
- : resolveEdrNetwork(newConfig, "", (strOrConfigVar) =>
160
- resolveConfigurationVariable(this.#hookManager, strOrConfigVar),
161
- );
162
- }
163
-
164
- const resolvedNetworkConfig =
165
- resolvedNetworkConfigOverride ??
166
- this.#networkConfigs[resolvedNetworkName];
143
+ const resolvedNetworkConfig = await this.#resolveNetworkConfig(
144
+ resolvedNetworkName,
145
+ networkConfigOverride,
146
+ );
167
147
 
168
148
  /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
169
149
  -- Cast to ChainTypeT because we know it's valid */
@@ -293,6 +273,88 @@ export class NetworkManagerImplementation implements NetworkManager {
293
273
  );
294
274
  }
295
275
 
276
+ /**
277
+ * Resolve the network connection configuration settings for the network name
278
+ * and taking into account any configuration overrides.
279
+ *
280
+ * @param resolvedNetworkName the network name for selecting the appropriate network config
281
+ * @param networkConfigOverride any network config options to override the
282
+ * defaults for the named network
283
+ * @returns a valid network configuration including any config additions from
284
+ * plugins
285
+ */
286
+ async #resolveNetworkConfig(
287
+ resolvedNetworkName: string,
288
+ networkConfigOverride: NetworkConfigOverride | undefined,
289
+ ): Promise<NetworkConfig> {
290
+ if (networkConfigOverride === undefined) {
291
+ return this.#networkConfigs[resolvedNetworkName];
292
+ }
293
+
294
+ if (
295
+ "type" in networkConfigOverride &&
296
+ networkConfigOverride.type !==
297
+ this.#networkConfigs[resolvedNetworkName].type
298
+ ) {
299
+ throw new HardhatError(
300
+ HardhatError.ERRORS.CORE.NETWORK.INVALID_CONFIG_OVERRIDE,
301
+ {
302
+ errors: `\t* The type of the network cannot be changed.`,
303
+ },
304
+ );
305
+ }
306
+
307
+ const newConfig = deepMerge(this.#userConfig, {
308
+ networks: {
309
+ [resolvedNetworkName]: networkConfigOverride,
310
+ },
311
+ });
312
+
313
+ // This is safe, the plugins used in resolution are registered
314
+ // with the hook handler, this property is only used for
315
+ // ensuring the original plugins are available at the end
316
+ // of resolution.
317
+ const resolvedPlugins: HardhatPlugin[] = [];
318
+
319
+ const configResolutionResult = await resolveUserConfigToHardhatConfig(
320
+ newConfig,
321
+ this.#hookManager,
322
+ this.#projectRoot,
323
+ this.#userProvidedConfigPath,
324
+ resolvedPlugins,
325
+ );
326
+
327
+ if (!configResolutionResult.success) {
328
+ throw new HardhatError(
329
+ HardhatError.ERRORS.CORE.NETWORK.INVALID_CONFIG_OVERRIDE,
330
+ {
331
+ errors: `\t${configResolutionResult.userConfigValidationErrors
332
+ .map((error) => {
333
+ const path = this.#normaliseErrorPathToNetworkConfig(
334
+ error.path,
335
+ resolvedNetworkName,
336
+ );
337
+
338
+ return path.length > 0
339
+ ? `* Error in ${path.join(".")}: ${error.message}`
340
+ : `* ${error.message}`;
341
+ })
342
+ .join("\n\t")}`,
343
+ },
344
+ );
345
+ }
346
+
347
+ const resolvedNetworkConfigOverride =
348
+ configResolutionResult.config.networks[resolvedNetworkName];
349
+
350
+ assertHardhatInvariant(
351
+ resolvedNetworkConfigOverride !== undefined,
352
+ "The overridden network config should translate through the hook resolution of user config",
353
+ );
354
+
355
+ return resolvedNetworkConfigOverride;
356
+ }
357
+
296
358
  async #getBuildInfosAndOutputsAsBuffers(): Promise<
297
359
  Array<{ buildInfo: Uint8Array; output: Uint8Array }>
298
360
  > {
@@ -315,4 +377,19 @@ export class NetworkManagerImplementation implements NetworkManager {
315
377
 
316
378
  return results;
317
379
  }
380
+
381
+ #normaliseErrorPathToNetworkConfig(
382
+ path: Array<string | number>,
383
+ resolvedNetworkName: string,
384
+ ): Array<string | number> {
385
+ if (path[0] !== undefined && path[0] === "networks") {
386
+ path = path.slice(1);
387
+ }
388
+
389
+ if (path[0] !== undefined && path[0] === resolvedNetworkName) {
390
+ path = path.slice(1);
391
+ }
392
+
393
+ return path;
394
+ }
318
395
  }
@@ -346,7 +346,7 @@ function refineEdrNetworkUserConfig(
346
346
  }
347
347
 
348
348
  const resolvedHardfork = hardfork ?? getCurrentHardfork(chainType);
349
- if (chainType === L1_CHAIN_TYPE || chainType === GENERIC_CHAIN_TYPE) {
349
+ if (chainType === L1_CHAIN_TYPE) {
350
350
  if (hardforkGte(resolvedHardfork, L1HardforkName.LONDON, chainType)) {
351
351
  if (minGasPrice !== undefined) {
352
352
  ctx.addIssue({
@@ -404,8 +404,8 @@ const userConfigSchema = z.object({
404
404
 
405
405
  const networkConfigOverrideSchema = z
406
406
  .discriminatedUnion("type", [
407
- httpNetworkUserConfigSchema.strict(),
408
- edrNetworkUserConfigSchema.strict(),
407
+ httpNetworkUserConfigSchema.passthrough(),
408
+ edrNetworkUserConfigSchema.passthrough(),
409
409
  ])
410
410
  .superRefine(refineEdrNetworkUserConfig);
411
411
 
@@ -0,0 +1,82 @@
1
+ import type { FSWatcher } from "chokidar";
2
+
3
+ import path from "node:path";
4
+
5
+ import debug from "debug";
6
+
7
+ export type BuildInfoWatcher = FSWatcher;
8
+ export type BuildInfoHandler = (buildId: string) => Promise<void>;
9
+
10
+ const log = debug("hardhat:core:tasks:node:artifacts");
11
+
12
+ const STABILITY_THRESHOLD = 250;
13
+ const POLL_INTERVAL = 50;
14
+
15
+ /**
16
+ * `listener` is a callback function invoked when a new file is added to the
17
+ * build info directory. It processes the received event to check whether it is
18
+ * for a build info file.
19
+ *
20
+ * If so, it extracts the build id from it and triggers the provided handler
21
+ * with the extracted build id as an argument. Any errors encountered during
22
+ * handler execution are captured and logged.
23
+ *
24
+ * @param absolutePath - The absolute path of the file added to the build info directory.
25
+ *
26
+ * This function is exposed for testing purposes only.
27
+ */
28
+ export async function listener(
29
+ handler: BuildInfoHandler,
30
+ absolutePath: string,
31
+ ): Promise<void> {
32
+ log(`Detected change in ${absolutePath}`);
33
+
34
+ const isBuildInfoFile =
35
+ absolutePath.endsWith(".json") && !absolutePath.endsWith(".output.json");
36
+
37
+ if (!isBuildInfoFile) {
38
+ log(`File ${absolutePath} is not a build info file`);
39
+ return;
40
+ }
41
+
42
+ const buildId = path.basename(absolutePath).replace(".json", "");
43
+
44
+ await handler(buildId).catch(async (error: unknown) => {
45
+ log(
46
+ `There was a problem executing the handler for build ${buildId}.`,
47
+ error,
48
+ );
49
+ });
50
+ }
51
+
52
+ /**
53
+ * `watchBuildInfo` is a function that creates a watch over provided build info
54
+ * directory. If it encounters a build info file being added, it will trigger
55
+ * the provided handler, passing the build id as an argument. This allows for
56
+ * further processing or actions to be taken upon completion of a build.
57
+ */
58
+ export async function watchBuildInfo(
59
+ buildInfoDirPath: string,
60
+ handler: BuildInfoHandler,
61
+ ): Promise<BuildInfoWatcher> {
62
+ const { watch } = await import("chokidar");
63
+
64
+ // NOTE: Deleting the build info directory while it is being watched will
65
+ // effectively cause the watcher to stop working.
66
+ // NOTE: We use chokidar's `awaitWriteFinish` option because we are certain
67
+ // the build info file will be added after the build info output file.
68
+ const watcher = watch(buildInfoDirPath, {
69
+ persistent: true,
70
+ ignoreInitial: true,
71
+ awaitWriteFinish: {
72
+ stabilityThreshold: STABILITY_THRESHOLD,
73
+ pollInterval: POLL_INTERVAL,
74
+ },
75
+ });
76
+
77
+ // NOTE: We listen only to the "add" event because the contents of the build info
78
+ // files identified by a build id should be considered immutable under usual circumstances.
79
+ watcher.on("add", listener.bind(null, handler));
80
+
81
+ return watcher;
82
+ }
@@ -1,9 +1,19 @@
1
+ import type { BuildInfo } from "../../../types/artifacts.js";
1
2
  import type { EdrNetworkAccountsConfig } from "../../../types/config.js";
3
+ import type { SolidityBuildInfoOutput } from "../../../types/solidity.js";
4
+ import type { EdrProvider } from "../network-manager/edr/edr-provider.js";
2
5
 
6
+ import path from "node:path";
7
+
8
+ import {
9
+ readJsonFile,
10
+ readJsonFileAsStream,
11
+ } from "@nomicfoundation/hardhat-utils/fs";
3
12
  import { hexStringToBytes } from "@nomicfoundation/hardhat-utils/hex";
4
13
  import chalk from "chalk";
5
14
  import { addr } from "micro-eth-signer";
6
15
 
16
+ import { sendErrorTelemetry } from "../../cli/telemetry/sentry/reporter.js";
7
17
  import { isDefaultEdrNetworkHDAccountsConfig } from "../network-manager/edr/edr-provider.js";
8
18
  import { normalizeEdrNetworkAccountsConfig } from "../network-manager/edr/utils/convert-to-edr.js";
9
19
 
@@ -64,6 +74,60 @@ export async function formatEdrNetworkConfigAccounts(
64
74
  return formattedAccountsLines.join("\n");
65
75
  }
66
76
 
77
+ /**
78
+ * Creates a handler function that will be called on buildInfo file creations
79
+ * (triggered from the compilation pipeline); the handler reads the build info
80
+ * file and uploads the key details into the EDR instance.
81
+ *
82
+ * @param buildInfoDirPath - The path (under artifacts) to the build info
83
+ * directory
84
+ * @param provider - The EDR provider being updated.
85
+ * @returns The handler function that is called with the buildId to upload.
86
+ */
87
+ export function createBuildInfoUploadHandlerFrom(
88
+ buildInfoDirPath: string,
89
+ provider: EdrProvider,
90
+ log: debug.Debugger,
91
+ ): (buildId: string) => Promise<void> {
92
+ const buildInfoHandler = async (buildId: string) => {
93
+ try {
94
+ log(`Adding new compilation result for build ${buildId} to the node`);
95
+ const buildInfo: BuildInfo = await readJsonFile(
96
+ path.join(buildInfoDirPath, `${buildId}.json`),
97
+ );
98
+ const buildInfoOutput: SolidityBuildInfoOutput =
99
+ await readJsonFileAsStream(
100
+ path.join(buildInfoDirPath, `${buildId}.output.json`),
101
+ );
102
+
103
+ await provider.addCompilationResult(
104
+ buildInfo.solcVersion,
105
+ buildInfo.input,
106
+ buildInfoOutput.output,
107
+ );
108
+
109
+ log(`Added compiler result for ${buildId}`);
110
+ } catch (error) {
111
+ console.warn(
112
+ chalk.yellow(
113
+ `There was a problem adding the new compiler result for build ${buildId}.`,
114
+ ),
115
+ );
116
+
117
+ log(
118
+ "Last compilation result couldn't be added. Please report this to help us improve Hardhat.\n",
119
+ error,
120
+ );
121
+
122
+ if (error instanceof Error) {
123
+ await sendErrorTelemetry(error);
124
+ }
125
+ }
126
+ };
127
+
128
+ return buildInfoHandler;
129
+ }
130
+
67
131
  // NOTE: This function is exported for testing purposes only
68
132
  export function getPublicPrivateKeysWarning(): string {
69
133
  return chalk.bold(
@@ -1,3 +1,4 @@
1
+ import type { JsonRpcServer } from "../../../../types/network.js";
1
2
  import type { EthereumProvider } from "../../../../types/providers.js";
2
3
  import type { Server } from "node:http";
3
4
  import type { AddressInfo } from "node:net";
@@ -11,17 +12,9 @@ import { JsonRpcHandler } from "./handler.js";
11
12
 
12
13
  const log = debug("hardhat:core:tasks:node:json-rpc:server");
13
14
 
14
- export interface JsonRpcServer {
15
- listen(): Promise<{ address: string; port: number }>;
16
- waitUntilClosed(): Promise<void>;
17
-
18
- close(): Promise<void>;
19
- }
20
-
21
15
  export interface JsonRpcServerConfig {
22
16
  hostname: string;
23
- port: number;
24
-
17
+ port?: number;
25
18
  provider: EthereumProvider;
26
19
  }
27
20
 
@@ -56,7 +49,7 @@ export class JsonRpcServerImplementation implements JsonRpcServer {
56
49
  });
57
50
  };
58
51
 
59
- public waitUntilClosed = async (): Promise<void> => {
52
+ public afterClosed = async (): Promise<void> => {
60
53
  const httpServerClosed = new Promise((resolve) => {
61
54
  this.#httpServer.once("close", resolve);
62
55
  });