hardhat 3.1.10 → 3.1.11

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 (186) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/src/internal/builtin-plugins/artifacts/artifact-manager.d.ts +2 -2
  3. package/dist/src/internal/builtin-plugins/artifacts/artifact-manager.d.ts.map +1 -1
  4. package/dist/src/internal/builtin-plugins/artifacts/artifact-manager.js.map +1 -1
  5. package/dist/src/internal/builtin-plugins/artifacts/hook-handlers/hre.d.ts.map +1 -1
  6. package/dist/src/internal/builtin-plugins/artifacts/hook-handlers/hre.js.map +1 -1
  7. package/dist/src/internal/builtin-plugins/coverage/helpers.d.ts +3 -5
  8. package/dist/src/internal/builtin-plugins/coverage/helpers.d.ts.map +1 -1
  9. package/dist/src/internal/builtin-plugins/coverage/helpers.js +7 -19
  10. package/dist/src/internal/builtin-plugins/coverage/helpers.js.map +1 -1
  11. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/test.d.ts +7 -0
  12. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/test.d.ts.map +1 -0
  13. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/test.js +42 -0
  14. package/dist/src/internal/builtin-plugins/coverage/hook-handlers/test.js.map +1 -0
  15. package/dist/src/internal/builtin-plugins/coverage/index.d.ts.map +1 -1
  16. package/dist/src/internal/builtin-plugins/coverage/index.js +1 -0
  17. package/dist/src/internal/builtin-plugins/coverage/index.js.map +1 -1
  18. package/dist/src/internal/builtin-plugins/gas-analytics/helpers.d.ts +3 -5
  19. package/dist/src/internal/builtin-plugins/gas-analytics/helpers.d.ts.map +1 -1
  20. package/dist/src/internal/builtin-plugins/gas-analytics/helpers.js +7 -19
  21. package/dist/src/internal/builtin-plugins/gas-analytics/helpers.js.map +1 -1
  22. package/dist/src/internal/builtin-plugins/gas-analytics/hook-handlers/test.d.ts +7 -0
  23. package/dist/src/internal/builtin-plugins/gas-analytics/hook-handlers/test.d.ts.map +1 -0
  24. package/dist/src/internal/builtin-plugins/gas-analytics/hook-handlers/test.js +42 -0
  25. package/dist/src/internal/builtin-plugins/gas-analytics/hook-handlers/test.js.map +1 -0
  26. package/dist/src/internal/builtin-plugins/gas-analytics/index.d.ts.map +1 -1
  27. package/dist/src/internal/builtin-plugins/gas-analytics/index.js +1 -0
  28. package/dist/src/internal/builtin-plugins/gas-analytics/index.js.map +1 -1
  29. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-provider.d.ts.map +1 -1
  30. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-provider.js +17 -20
  31. package/dist/src/internal/builtin-plugins/network-manager/edr/edr-provider.js.map +1 -1
  32. package/dist/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-generation-errors.d.ts +1 -1
  33. package/dist/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-generation-errors.d.ts.map +1 -1
  34. package/dist/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-generation-errors.js +2 -2
  35. package/dist/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-generation-errors.js.map +1 -1
  36. package/dist/src/internal/builtin-plugins/network-manager/edr/type-validation.d.ts +0 -2
  37. package/dist/src/internal/builtin-plugins/network-manager/edr/type-validation.d.ts.map +1 -1
  38. package/dist/src/internal/builtin-plugins/network-manager/edr/type-validation.js +0 -6
  39. package/dist/src/internal/builtin-plugins/network-manager/edr/type-validation.js.map +1 -1
  40. package/dist/src/internal/builtin-plugins/network-manager/edr/utils/convert-to-edr.d.ts +1 -3
  41. package/dist/src/internal/builtin-plugins/network-manager/edr/utils/convert-to-edr.d.ts.map +1 -1
  42. package/dist/src/internal/builtin-plugins/network-manager/edr/utils/convert-to-edr.js +0 -49
  43. package/dist/src/internal/builtin-plugins/network-manager/edr/utils/convert-to-edr.js.map +1 -1
  44. package/dist/src/internal/builtin-plugins/solidity/build-results.d.ts +2 -2
  45. package/dist/src/internal/builtin-plugins/solidity/build-results.d.ts.map +1 -1
  46. package/dist/src/internal/builtin-plugins/solidity/build-results.js +2 -2
  47. package/dist/src/internal/builtin-plugins/solidity/build-results.js.map +1 -1
  48. package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.d.ts +1 -0
  49. package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.d.ts.map +1 -1
  50. package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.js +13 -5
  51. package/dist/src/internal/builtin-plugins/solidity/build-system/build-system.js.map +1 -1
  52. package/dist/src/internal/builtin-plugins/solidity/build-system/compiler/compiler.js +1 -1
  53. package/dist/src/internal/builtin-plugins/solidity/build-system/compiler/compiler.js.map +1 -1
  54. package/dist/src/internal/builtin-plugins/solidity/build-system/dependency-graph.d.ts +1 -1
  55. package/dist/src/internal/builtin-plugins/solidity/build-system/dependency-graph.js +1 -1
  56. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.d.ts +2 -1
  57. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.d.ts.map +1 -1
  58. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.d.ts +13 -1
  59. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.d.ts.map +1 -1
  60. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.js +30 -5
  61. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.js.map +1 -1
  62. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/types.d.ts +3 -12
  63. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/types.d.ts.map +1 -1
  64. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/types.js.map +1 -1
  65. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/utils.d.ts +1 -1
  66. package/dist/src/internal/builtin-plugins/solidity/build-system/resolver/utils.d.ts.map +1 -1
  67. package/dist/src/internal/builtin-plugins/solidity/build-system/solc-config-selection.d.ts +8 -6
  68. package/dist/src/internal/builtin-plugins/solidity/build-system/solc-config-selection.d.ts.map +1 -1
  69. package/dist/src/internal/builtin-plugins/solidity/build-system/solc-config-selection.js +103 -27
  70. package/dist/src/internal/builtin-plugins/solidity/build-system/solc-config-selection.js.map +1 -1
  71. package/dist/src/internal/builtin-plugins/solidity/config.js +2 -2
  72. package/dist/src/internal/builtin-plugins/solidity/config.js.map +1 -1
  73. package/dist/src/internal/builtin-plugins/solidity/hook-handlers/hre.d.ts.map +1 -1
  74. package/dist/src/internal/builtin-plugins/solidity/hook-handlers/hre.js +5 -0
  75. package/dist/src/internal/builtin-plugins/solidity/hook-handlers/hre.js.map +1 -1
  76. package/dist/src/internal/builtin-plugins/solidity/tasks/build.js +1 -1
  77. package/dist/src/internal/builtin-plugins/solidity/tasks/build.js.map +1 -1
  78. package/dist/src/internal/builtin-plugins/solidity-test/edr-artifacts.d.ts +1 -1
  79. package/dist/src/internal/builtin-plugins/solidity-test/edr-artifacts.d.ts.map +1 -1
  80. package/dist/src/internal/builtin-plugins/solidity-test/edr-artifacts.js +1 -1
  81. package/dist/src/internal/builtin-plugins/solidity-test/edr-artifacts.js.map +1 -1
  82. package/dist/src/internal/builtin-plugins/solidity-test/runner.d.ts +1 -1
  83. package/dist/src/internal/builtin-plugins/solidity-test/runner.js +1 -1
  84. package/dist/src/internal/builtin-plugins/solidity-test/task-action.d.ts.map +1 -1
  85. package/dist/src/internal/builtin-plugins/solidity-test/task-action.js +16 -27
  86. package/dist/src/internal/builtin-plugins/solidity-test/task-action.js.map +1 -1
  87. package/dist/src/internal/builtin-plugins/telemetry/task-action.d.ts.map +1 -1
  88. package/dist/src/internal/builtin-plugins/telemetry/task-action.js +3 -2
  89. package/dist/src/internal/builtin-plugins/telemetry/task-action.js.map +1 -1
  90. package/dist/src/internal/builtin-plugins/test/task-action.d.ts.map +1 -1
  91. package/dist/src/internal/builtin-plugins/test/task-action.js +40 -13
  92. package/dist/src/internal/builtin-plugins/test/task-action.js.map +1 -1
  93. package/dist/src/internal/builtin-plugins/test/type-extensions.d.ts +27 -0
  94. package/dist/src/internal/builtin-plugins/test/type-extensions.d.ts.map +1 -1
  95. package/dist/src/internal/cli/banner-manager.d.ts +26 -0
  96. package/dist/src/internal/cli/banner-manager.d.ts.map +1 -0
  97. package/dist/src/internal/cli/banner-manager.js +146 -0
  98. package/dist/src/internal/cli/banner-manager.js.map +1 -0
  99. package/dist/src/internal/cli/init/init.d.ts.map +1 -1
  100. package/dist/src/internal/cli/init/init.js +8 -0
  101. package/dist/src/internal/cli/init/init.js.map +1 -1
  102. package/dist/src/internal/cli/main.d.ts.map +1 -1
  103. package/dist/src/internal/cli/main.js +18 -1
  104. package/dist/src/internal/cli/main.js.map +1 -1
  105. package/dist/src/internal/cli/telemetry/analytics/subprocess.js +2 -0
  106. package/dist/src/internal/cli/telemetry/analytics/subprocess.js.map +1 -1
  107. package/dist/src/internal/cli/telemetry/sentry/anonymize-paths.js +1 -1
  108. package/dist/src/internal/cli/telemetry/sentry/vendor/integrations/contextlines.d.ts +1 -1
  109. package/dist/src/internal/cli/telemetry/sentry/vendor/integrations/contextlines.d.ts.map +1 -1
  110. package/dist/src/internal/cli/telemetry/sentry/vendor/integrations/contextlines.js +47 -38
  111. package/dist/src/internal/cli/telemetry/sentry/vendor/integrations/contextlines.js.map +1 -1
  112. package/dist/src/internal/core/user-interruptions.js +1 -1
  113. package/dist/src/types/artifacts.d.ts +32 -3
  114. package/dist/src/types/artifacts.d.ts.map +1 -1
  115. package/dist/src/types/network.d.ts +1 -1
  116. package/dist/src/types/solidity/build-system.d.ts +56 -10
  117. package/dist/src/types/solidity/build-system.d.ts.map +1 -1
  118. package/dist/src/types/solidity/build-system.js +26 -2
  119. package/dist/src/types/solidity/build-system.js.map +1 -1
  120. package/dist/src/types/solidity/resolved-file.d.ts +2 -2
  121. package/dist/src/types/tasks.d.ts +8 -0
  122. package/dist/src/types/tasks.d.ts.map +1 -1
  123. package/dist/src/types/tasks.js.map +1 -1
  124. package/dist/src/types/test.d.ts +11 -0
  125. package/dist/src/types/test.d.ts.map +1 -1
  126. package/dist/src/types/utils.d.ts +16 -0
  127. package/dist/src/types/utils.d.ts.map +1 -1
  128. package/dist/src/utils/result.d.ts +33 -0
  129. package/dist/src/utils/result.d.ts.map +1 -0
  130. package/dist/src/utils/result.js +43 -0
  131. package/dist/src/utils/result.js.map +1 -0
  132. package/package.json +4 -3
  133. package/src/internal/builtin-plugins/artifacts/artifact-manager.ts +4 -1
  134. package/src/internal/builtin-plugins/artifacts/hook-handlers/hre.ts +4 -1
  135. package/src/internal/builtin-plugins/coverage/helpers.ts +11 -29
  136. package/src/internal/builtin-plugins/coverage/hook-handlers/test.ts +68 -0
  137. package/src/internal/builtin-plugins/coverage/index.ts +1 -0
  138. package/src/internal/builtin-plugins/gas-analytics/helpers.ts +11 -29
  139. package/src/internal/builtin-plugins/gas-analytics/hook-handlers/test.ts +68 -0
  140. package/src/internal/builtin-plugins/gas-analytics/index.ts +1 -0
  141. package/src/internal/builtin-plugins/network-manager/edr/edr-provider.ts +21 -28
  142. package/src/internal/builtin-plugins/network-manager/edr/stack-traces/stack-trace-generation-errors.ts +5 -2
  143. package/src/internal/builtin-plugins/network-manager/edr/type-validation.ts +0 -13
  144. package/src/internal/builtin-plugins/network-manager/edr/utils/convert-to-edr.ts +0 -64
  145. package/src/internal/builtin-plugins/solidity/build-results.ts +3 -1
  146. package/src/internal/builtin-plugins/solidity/build-system/build-system.ts +15 -5
  147. package/src/internal/builtin-plugins/solidity/build-system/compiler/compiler.ts +1 -1
  148. package/src/internal/builtin-plugins/solidity/build-system/dependency-graph.ts +1 -1
  149. package/src/internal/builtin-plugins/solidity/build-system/resolver/dependency-resolver.ts +1 -1
  150. package/src/internal/builtin-plugins/solidity/build-system/resolver/remapped-npm-packages-graph.ts +36 -6
  151. package/src/internal/builtin-plugins/solidity/build-system/resolver/types.ts +3 -9
  152. package/src/internal/builtin-plugins/solidity/build-system/resolver/utils.ts +1 -1
  153. package/src/internal/builtin-plugins/solidity/build-system/solc-config-selection.ts +125 -28
  154. package/src/internal/builtin-plugins/solidity/config.ts +2 -2
  155. package/src/internal/builtin-plugins/solidity/hook-handlers/hre.ts +8 -0
  156. package/src/internal/builtin-plugins/solidity/tasks/build.ts +1 -1
  157. package/src/internal/builtin-plugins/solidity-test/edr-artifacts.ts +2 -2
  158. package/src/internal/builtin-plugins/solidity-test/runner.ts +1 -1
  159. package/src/internal/builtin-plugins/solidity-test/task-action.ts +36 -38
  160. package/src/internal/builtin-plugins/telemetry/task-action.ts +4 -2
  161. package/src/internal/builtin-plugins/test/task-action.ts +71 -25
  162. package/src/internal/builtin-plugins/test/type-extensions.ts +42 -0
  163. package/src/internal/cli/banner-manager.ts +234 -0
  164. package/src/internal/cli/init/init.ts +8 -0
  165. package/src/internal/cli/main.ts +19 -1
  166. package/src/internal/cli/telemetry/analytics/subprocess.ts +2 -0
  167. package/src/internal/cli/telemetry/sentry/anonymize-paths.ts +1 -1
  168. package/src/internal/cli/telemetry/sentry/vendor/integrations/contextlines.ts +98 -50
  169. package/src/internal/core/user-interruptions.ts +1 -1
  170. package/src/types/artifacts.ts +40 -3
  171. package/src/types/hre.ts +1 -1
  172. package/src/types/network.ts +1 -1
  173. package/src/types/solidity/build-system.ts +75 -14
  174. package/src/types/solidity/resolved-file.ts +2 -2
  175. package/src/types/tasks.ts +10 -0
  176. package/src/types/test.ts +12 -0
  177. package/src/types/utils.ts +14 -0
  178. package/src/utils/result.ts +57 -0
  179. package/templates/hardhat-3/01-node-test-runner-viem/package.json +9 -9
  180. package/templates/hardhat-3/02-mocha-ethers/package.json +10 -10
  181. package/templates/hardhat-3/03-minimal/package.json +1 -1
  182. package/dist/src/internal/builtin-plugins/network-manager/edr/types/output.d.ts +0 -19
  183. package/dist/src/internal/builtin-plugins/network-manager/edr/types/output.d.ts.map +0 -1
  184. package/dist/src/internal/builtin-plugins/network-manager/edr/types/output.js +0 -2
  185. package/dist/src/internal/builtin-plugins/network-manager/edr/types/output.js.map +0 -1
  186. package/src/internal/builtin-plugins/network-manager/edr/types/output.ts +0 -19
@@ -39,5 +39,47 @@ declare module "../../../types/hooks.js" {
39
39
  filePath: string,
40
40
  ) => Promise<string | undefined>,
41
41
  ) => Promise<string | undefined>;
42
+
43
+ /**
44
+ * This hook is triggered at the start of a test run, before tests execute.
45
+ *
46
+ * @param context The hook context.
47
+ * @param id A string identifier for the test runner (e.g., "solidity", "nodejs", "mocha").
48
+ * @param next A function to call the next handler for this hook, or the
49
+ * default implementation if no more handlers exist.
50
+ */
51
+ onTestRunStart: (
52
+ context: HookContext,
53
+ id: string,
54
+ next: (nextContext: HookContext, id: string) => Promise<void>,
55
+ ) => Promise<void>;
56
+
57
+ /**
58
+ * This hook is triggered when a test worker has finished executing.
59
+ *
60
+ * @param context The hook context.
61
+ * @param id A string identifier for the test runner (e.g., "solidity", "nodejs", "mocha").
62
+ * @param next A function to call the next handler for this hook, or the
63
+ * default implementation if no more handlers exist.
64
+ */
65
+ onTestWorkerDone: (
66
+ context: HookContext,
67
+ id: string,
68
+ next: (nextContext: HookContext, id: string) => Promise<void>,
69
+ ) => Promise<void>;
70
+
71
+ /**
72
+ * This hook is triggered at the end of a test run, after all tests have completed.
73
+ *
74
+ * @param context The hook context.
75
+ * @param id A string identifier for the test runner (e.g., "solidity", "nodejs", "mocha").
76
+ * @param next A function to call the next handler for this hook, or the
77
+ * default implementation if no more handlers exist.
78
+ */
79
+ onTestRunDone: (
80
+ context: HookContext,
81
+ id: string,
82
+ next: (nextContext: HookContext, id: string) => Promise<void>,
83
+ ) => Promise<void>;
42
84
  }
43
85
  }
@@ -0,0 +1,234 @@
1
+ import type { Dispatcher } from "@nomicfoundation/hardhat-utils/request";
2
+
3
+ import path from "node:path";
4
+
5
+ import {
6
+ readJsonFile,
7
+ writeJsonFile,
8
+ FileNotFoundError,
9
+ } from "@nomicfoundation/hardhat-utils/fs";
10
+ import { getCacheDir } from "@nomicfoundation/hardhat-utils/global-dir";
11
+ import { isObject } from "@nomicfoundation/hardhat-utils/lang";
12
+ import { getRequest } from "@nomicfoundation/hardhat-utils/request";
13
+ import debug from "debug";
14
+
15
+ const log = debug("hardhat:util:banner-manager");
16
+
17
+ interface BannerConfig {
18
+ enabled: boolean;
19
+ formattedMessages: string[];
20
+ minSecondsBetweenDisplays: number;
21
+ minSecondsBetweenRequests: number;
22
+ }
23
+
24
+ export const BANNER_CONFIG_URL =
25
+ "https://raw.githubusercontent.com/NomicFoundation/hardhat/refs/heads/main/banner-config-v3.json";
26
+
27
+ export const BANNER_CACHE_FILE_NAME = "banner-config-v3.json";
28
+
29
+ export class BannerManager {
30
+ static #instance: BannerManager | undefined;
31
+
32
+ #bannerConfig: BannerConfig | undefined;
33
+ #lastDisplayTime: number;
34
+ #lastRequestTime: number;
35
+ readonly #dispatcher: Dispatcher | undefined;
36
+ readonly #print: (message: string) => void;
37
+
38
+ private constructor(
39
+ bannerConfig: BannerConfig | undefined,
40
+ lastDisplayTime: number,
41
+ lastRequestTime: number,
42
+ dispatcher: Dispatcher | undefined,
43
+ print: (message: string) => void,
44
+ ) {
45
+ this.#bannerConfig = bannerConfig;
46
+ this.#lastDisplayTime = lastDisplayTime;
47
+ this.#lastRequestTime = lastRequestTime;
48
+ this.#dispatcher = dispatcher;
49
+ this.#print = print;
50
+ }
51
+
52
+ /**
53
+ * Returns a global instance of BannerManager.
54
+ *
55
+ * @param options Options used for testing purposes. Only used in the first
56
+ * invocation of this function, or after calling `resetInstance`.
57
+ * @returns The current global instance of BannerManager.
58
+ */
59
+ public static async getInstance(options?: {
60
+ testDispatcher?: Dispatcher;
61
+ print?: (message: string) => void;
62
+ }): Promise<BannerManager> {
63
+ if (this.#instance === undefined) {
64
+ log("Initializing BannerManager");
65
+ const { bannerConfig, lastDisplayTime, lastRequestTime } =
66
+ await readCache();
67
+ this.#instance = new BannerManager(
68
+ bannerConfig,
69
+ lastDisplayTime,
70
+ lastRequestTime,
71
+ options?.testDispatcher,
72
+ options?.print ?? console.log,
73
+ );
74
+ }
75
+
76
+ return this.#instance;
77
+ }
78
+
79
+ public static resetInstance(): void {
80
+ this.#instance = undefined;
81
+ }
82
+
83
+ /**
84
+ * Displays a banner message, if any.
85
+ *
86
+ * @param timeout The timeout in milliseconds to wait for the banner display.
87
+ */
88
+ public async showBanner(timeout?: number): Promise<void> {
89
+ await this.#requestBannerConfig(timeout);
90
+
91
+ if (
92
+ this.#bannerConfig === undefined ||
93
+ !this.#bannerConfig.enabled ||
94
+ this.#bannerConfig.formattedMessages.length === 0
95
+ ) {
96
+ log("Banner is disabled or no messages available.");
97
+ return;
98
+ }
99
+
100
+ const { formattedMessages, minSecondsBetweenDisplays } = this.#bannerConfig;
101
+
102
+ const timeSinceLastDisplay = Date.now() - this.#lastDisplayTime;
103
+ if (timeSinceLastDisplay < minSecondsBetweenDisplays * 1000) {
104
+ log(
105
+ `Skipping banner display. Time since last display: ${timeSinceLastDisplay}ms`,
106
+ );
107
+ return;
108
+ }
109
+
110
+ // select a random message from the formattedMessages array
111
+ const randomIndex = Math.floor(Math.random() * formattedMessages.length);
112
+ const message = formattedMessages[randomIndex];
113
+
114
+ this.#print(message);
115
+ this.#lastDisplayTime = Date.now();
116
+ await writeCache({
117
+ bannerConfig: this.#bannerConfig,
118
+ lastDisplayTime: this.#lastDisplayTime,
119
+ lastRequestTime: this.#lastRequestTime,
120
+ });
121
+ }
122
+
123
+ async #requestBannerConfig(timeout?: number): Promise<void> {
124
+ if (this.#bannerConfig !== undefined) {
125
+ const timeSinceLastRequest = Date.now() - this.#lastRequestTime;
126
+ if (
127
+ timeSinceLastRequest <
128
+ this.#bannerConfig.minSecondsBetweenRequests * 1000
129
+ ) {
130
+ log(
131
+ `Skipping banner config request. Time since last request: ${timeSinceLastRequest}ms`,
132
+ );
133
+ return;
134
+ }
135
+ }
136
+
137
+ try {
138
+ const response = await getRequest(
139
+ BANNER_CONFIG_URL,
140
+ undefined,
141
+ this.#dispatcher ?? { timeout },
142
+ );
143
+
144
+ const bannerConfig: unknown = await response.body.json();
145
+
146
+ if (!this.#isBannerConfig(bannerConfig)) {
147
+ log(`Invalid banner config received:`, bannerConfig);
148
+ return;
149
+ }
150
+
151
+ this.#bannerConfig = bannerConfig;
152
+ this.#lastRequestTime = Date.now();
153
+
154
+ await writeCache({
155
+ bannerConfig: this.#bannerConfig,
156
+ lastDisplayTime: this.#lastDisplayTime,
157
+ lastRequestTime: this.#lastRequestTime,
158
+ });
159
+ } catch (error) {
160
+ log(
161
+ `Error requesting banner config: ${
162
+ error instanceof Error ? error.message : JSON.stringify(error)
163
+ }`,
164
+ );
165
+ }
166
+ }
167
+
168
+ #isBannerConfig(value: unknown): value is BannerConfig {
169
+ if (!isObject(value)) {
170
+ return false;
171
+ }
172
+
173
+ return (
174
+ Object.getOwnPropertyNames(value).length === 4 &&
175
+ "enabled" in value &&
176
+ typeof value.enabled === "boolean" &&
177
+ "formattedMessages" in value &&
178
+ Array.isArray(value.formattedMessages) &&
179
+ value.formattedMessages.every(
180
+ (message: unknown) => typeof message === "string",
181
+ ) &&
182
+ "minSecondsBetweenDisplays" in value &&
183
+ typeof value.minSecondsBetweenDisplays === "number" &&
184
+ "minSecondsBetweenRequests" in value &&
185
+ typeof value.minSecondsBetweenRequests === "number"
186
+ );
187
+ }
188
+ }
189
+
190
+ interface BannerCache {
191
+ bannerConfig: BannerConfig | undefined;
192
+ lastDisplayTime: number;
193
+ lastRequestTime: number;
194
+ }
195
+
196
+ async function readCache(): Promise<BannerCache> {
197
+ const cacheDir = await getCacheDir();
198
+ const bannerCacheFilePath = path.join(cacheDir, BANNER_CACHE_FILE_NAME);
199
+
200
+ try {
201
+ return await readJsonFile<BannerCache>(bannerCacheFilePath);
202
+ } catch (error) {
203
+ if (error instanceof FileNotFoundError) {
204
+ log("No banner cache file found, using defaults");
205
+ } else {
206
+ log(
207
+ `Error reading cache file: ${
208
+ error instanceof Error ? error.message : JSON.stringify(error)
209
+ }`,
210
+ );
211
+ }
212
+
213
+ return {
214
+ bannerConfig: undefined,
215
+ lastDisplayTime: 0,
216
+ lastRequestTime: 0,
217
+ };
218
+ }
219
+ }
220
+
221
+ async function writeCache(cache: BannerCache): Promise<void> {
222
+ const cacheDir = await getCacheDir();
223
+ const bannerCacheFilePath = path.join(cacheDir, BANNER_CACHE_FILE_NAME);
224
+
225
+ try {
226
+ await writeJsonFile(bannerCacheFilePath, cache);
227
+ } catch (error) {
228
+ log(
229
+ `Error writing cache file: ${
230
+ error instanceof Error ? error.message : JSON.stringify(error)
231
+ }`,
232
+ );
233
+ }
234
+ }
@@ -131,6 +131,14 @@ export async function initHardhat(options?: InitHardhatOptions): Promise<void> {
131
131
  ]);
132
132
 
133
133
  showStarOnGitHubMessage();
134
+
135
+ try {
136
+ const { BannerManager } = await import("../banner-manager.js");
137
+ const bannerManager = await BannerManager.getInstance();
138
+ await bannerManager.showBanner();
139
+ } catch (bannerError) {
140
+ log("Error showing banner", bannerError);
141
+ }
134
142
  } catch (e) {
135
143
  if (e === "") {
136
144
  // If the user cancels any prompt, we quit silently
@@ -28,6 +28,7 @@ import {
28
28
  type OptionDefinition,
29
29
  type PositionalArgumentDefinition,
30
30
  } from "../../types/arguments.js";
31
+ import { isResult } from "../../utils/result.js";
31
32
  import { BUILTIN_GLOBAL_OPTIONS_DEFINITIONS } from "../builtin-global-options.js";
32
33
  import { builtinPlugins } from "../builtin-plugins/index.js";
33
34
  import {
@@ -217,7 +218,24 @@ export async function main(
217
218
 
218
219
  log(`Running task "${task.id.join(" ")}"`);
219
220
 
220
- await Promise.all([task.run(taskArguments), sendTaskAnalytics(task.id)]);
221
+ const [taskResult] = await Promise.all([
222
+ task.run(taskArguments),
223
+ sendTaskAnalytics(task.id),
224
+ ]);
225
+
226
+ if (isResult(taskResult) && !taskResult.success) {
227
+ process.exitCode = 1;
228
+ }
229
+
230
+ if (!isCi() && process.stdout.isTTY === true) {
231
+ try {
232
+ const { BannerManager } = await import("./banner-manager.js");
233
+ const bannerManager = await BannerManager.getInstance();
234
+ await bannerManager.showBanner(200);
235
+ } catch (bannerError) {
236
+ log("Error showing banner", bannerError);
237
+ }
238
+ }
221
239
  } catch (error) {
222
240
  ensureError(error);
223
241
  printErrorMessages(error, builtinGlobalOptions?.showStackTraces);
@@ -5,7 +5,9 @@ import { postJsonRequest } from "@nomicfoundation/hardhat-utils/request";
5
5
 
6
6
  // These keys are expected to be public
7
7
  const ANALYTICS_URL = "https://www.google-analytics.com/mp/collect";
8
+ /* cspell:disable-next-line */
8
9
  // const API_SECRET = "iXzTRik5RhahYpgiatSv1w"; // DEV
10
+ /* cspell:disable-next-line */
9
11
  // const MEASUREMENT_ID = "G-ZFZWHGZ64H"; // DEV
10
12
  const API_SECRET = "fQ5joCsDRTOp55wX8a2cVw"; // PROD
11
13
  const MEASUREMENT_ID = "G-8LQ007N2QJ"; // PROD
@@ -107,7 +107,7 @@ function anonymizeSinglePath(path: string): string {
107
107
  return normalizedPath;
108
108
  }
109
109
 
110
- // We first get the index of the first /node_modules to desambiguate some
110
+ // We first get the index of the first /node_modules to disambiguate some
111
111
  // special cases below
112
112
  const nodeModulesIndex = normalizedPath.indexOf("/node_modules");
113
113