hardhat 3.4.3 → 3.4.4
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.
- package/CHANGELOG.md +8 -0
- package/dist/src/internal/builtin-plugins/coverage/coverage-manager.d.ts +1 -1
- package/dist/src/internal/builtin-plugins/coverage/coverage-manager.d.ts.map +1 -1
- package/dist/src/internal/builtin-plugins/coverage/coverage-manager.js +9 -9
- package/dist/src/internal/builtin-plugins/coverage/coverage-manager.js.map +1 -1
- package/dist/src/internal/cli/telemetry/error-classification/classifier.d.ts +58 -0
- package/dist/src/internal/cli/telemetry/error-classification/classifier.d.ts.map +1 -0
- package/dist/src/internal/cli/telemetry/error-classification/classifier.js +402 -0
- package/dist/src/internal/cli/telemetry/error-classification/classifier.js.map +1 -0
- package/dist/src/internal/cli/telemetry/error-classification/codebase-dependent-helpers.d.ts +67 -0
- package/dist/src/internal/cli/telemetry/error-classification/codebase-dependent-helpers.d.ts.map +1 -0
- package/dist/src/internal/cli/telemetry/error-classification/codebase-dependent-helpers.js +140 -0
- package/dist/src/internal/cli/telemetry/error-classification/codebase-dependent-helpers.js.map +1 -0
- package/dist/src/internal/cli/telemetry/error-classification/filter.d.ts +15 -0
- package/dist/src/internal/cli/telemetry/error-classification/filter.d.ts.map +1 -0
- package/dist/src/internal/cli/telemetry/error-classification/filter.js +114 -0
- package/dist/src/internal/cli/telemetry/error-classification/filter.js.map +1 -0
- package/dist/src/internal/cli/telemetry/error-classification/helpers.d.ts +52 -0
- package/dist/src/internal/cli/telemetry/error-classification/helpers.d.ts.map +1 -0
- package/dist/src/internal/cli/telemetry/error-classification/helpers.js +163 -0
- package/dist/src/internal/cli/telemetry/error-classification/helpers.js.map +1 -0
- package/dist/src/internal/cli/telemetry/error-reporter/reporter.d.ts.map +1 -1
- package/dist/src/internal/cli/telemetry/error-reporter/reporter.js +14 -0
- package/dist/src/internal/cli/telemetry/error-reporter/reporter.js.map +1 -1
- package/dist/src/internal/cli/telemetry/sentry/anonymizer.d.ts +0 -2
- package/dist/src/internal/cli/telemetry/sentry/anonymizer.d.ts.map +1 -1
- package/dist/src/internal/cli/telemetry/sentry/anonymizer.js +0 -117
- package/dist/src/internal/cli/telemetry/sentry/anonymizer.js.map +1 -1
- package/dist/src/internal/cli/telemetry/sentry/init.d.ts.map +1 -1
- package/dist/src/internal/cli/telemetry/sentry/init.js +14 -9
- package/dist/src/internal/cli/telemetry/sentry/init.js.map +1 -1
- package/dist/src/internal/cli/telemetry/sentry/reporter.d.ts.map +1 -1
- package/dist/src/internal/cli/telemetry/sentry/reporter.js +1 -27
- package/dist/src/internal/cli/telemetry/sentry/reporter.js.map +1 -1
- package/dist/src/internal/cli/telemetry/sentry/subprocess.js +11 -17
- package/dist/src/internal/cli/telemetry/sentry/subprocess.js.map +1 -1
- package/package.json +1 -1
- package/src/internal/builtin-plugins/coverage/coverage-manager.ts +14 -10
- package/src/internal/cli/telemetry/error-classification/classifier.ts +636 -0
- package/src/internal/cli/telemetry/error-classification/codebase-dependent-helpers.ts +200 -0
- package/src/internal/cli/telemetry/error-classification/filter.ts +140 -0
- package/src/internal/cli/telemetry/error-classification/helpers.ts +235 -0
- package/src/internal/cli/telemetry/error-reporter/reporter.ts +21 -0
- package/src/internal/cli/telemetry/sentry/anonymizer.ts +0 -168
- package/src/internal/cli/telemetry/sentry/init.ts +42 -33
- package/src/internal/cli/telemetry/sentry/reporter.ts +1 -44
- package/src/internal/cli/telemetry/sentry/subprocess.ts +11 -19
- package/templates/hardhat-3/01-node-test-runner-viem/package.json +2 -2
- package/templates/hardhat-3/02-mocha-ethers/package.json +1 -1
- package/templates/hardhat-3/03-minimal/package.json +1 -1
|
@@ -153,174 +153,6 @@ export class Anonymizer {
|
|
|
153
153
|
);
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
public filterOutEventsWithExceptionsNotRaisedByHardhat(
|
|
157
|
-
envelope: Envelope,
|
|
158
|
-
): Envelope {
|
|
159
|
-
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions --
|
|
160
|
-
We are just filtering events in place, not changing any type */
|
|
161
|
-
envelope[1] = envelope[1].filter((item) => {
|
|
162
|
-
if (item[0].type !== "event") {
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
167
|
-
-- We know that the item is an event item */
|
|
168
|
-
const eventItem = item as EventItem;
|
|
169
|
-
|
|
170
|
-
return this.raisedByHardhat(eventItem[1]);
|
|
171
|
-
}) as any;
|
|
172
|
-
|
|
173
|
-
return envelope;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
public raisedByHardhat(event: Event): boolean {
|
|
177
|
-
const exceptions = event?.exception?.values;
|
|
178
|
-
|
|
179
|
-
if (exceptions === undefined) {
|
|
180
|
-
// if we can't prove that the exception doesn't come from hardhat,
|
|
181
|
-
// we err on the side of reporting the error
|
|
182
|
-
return true;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const originalException = exceptions[exceptions.length - 1];
|
|
186
|
-
|
|
187
|
-
if (!this.#isErrorMessageAllowed(originalException)) {
|
|
188
|
-
return false;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const frames = originalException?.stacktrace?.frames;
|
|
192
|
-
|
|
193
|
-
if (frames === undefined) {
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
for (const frame of frames.slice().reverse()) {
|
|
198
|
-
if (frame.filename === undefined) {
|
|
199
|
-
continue;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// We don't report errors from the Hardhat.config file
|
|
203
|
-
if (
|
|
204
|
-
this.#configPath !== undefined &&
|
|
205
|
-
this.#configPath.includes(frame.filename)
|
|
206
|
-
) {
|
|
207
|
-
return false;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (this.#isPackageFile(frame.filename)) {
|
|
211
|
-
// We don't report errors from the ignored package list e.g. `ethers`
|
|
212
|
-
// even when buried as a subpackage of a hardhat package
|
|
213
|
-
if (this.#errorRaisedByPackageToIgnore(frame.filename)) {
|
|
214
|
-
return false;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// We report errors from Hardhat packages, we exclude
|
|
218
|
-
// those from non-hardhat packages
|
|
219
|
-
return this.#isHardhatFile(frame.filename);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Error originating not in packages, but in the user project
|
|
223
|
-
// should be filtered.
|
|
224
|
-
if (this.#isUserProjectFile(frame.filename)) {
|
|
225
|
-
return false;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Otherwise look at the next frame up
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// if we didn't find any hardhat frame, we don't report the error
|
|
232
|
-
return false;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
#isErrorMessageAllowed(originalException: Exception): boolean {
|
|
236
|
-
const exceptionType = originalException.type;
|
|
237
|
-
const exceptionMessage = originalException.value;
|
|
238
|
-
|
|
239
|
-
// Without an exception message, we can't filter so allow it
|
|
240
|
-
if (exceptionMessage === undefined) {
|
|
241
|
-
return true;
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Filter out required not defined in ES Modules errors
|
|
245
|
-
if (
|
|
246
|
-
exceptionType === "ReferenceError" &&
|
|
247
|
-
exceptionMessage ===
|
|
248
|
-
"require is not defined in ES module scope, you can use import instead"
|
|
249
|
-
) {
|
|
250
|
-
return false;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Filter out cannot find package when importing errors
|
|
254
|
-
if (
|
|
255
|
-
exceptionType === "Error" &&
|
|
256
|
-
/^Cannot find package '([^']+)' imported from .+$/.test(exceptionMessage)
|
|
257
|
-
) {
|
|
258
|
-
return false;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Filter out cannot find module errors
|
|
262
|
-
if (
|
|
263
|
-
exceptionType === "Error" &&
|
|
264
|
-
/^Cannot find module '([^']+)'/.test(exceptionMessage)
|
|
265
|
-
) {
|
|
266
|
-
return false;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// Filter out "require() cannot be sued on an ESM graph"
|
|
270
|
-
if (
|
|
271
|
-
exceptionType === "Error" &&
|
|
272
|
-
exceptionMessage.startsWith(
|
|
273
|
-
"require() cannot be used on an ESM graph with top-level await. Use import() instead.",
|
|
274
|
-
)
|
|
275
|
-
) {
|
|
276
|
-
return false;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
return true;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
#errorRaisedByPackageToIgnore(filename: string): boolean {
|
|
283
|
-
// List of external packages that we don't want to report errors from
|
|
284
|
-
const pkgsToIgnore: string[] = [
|
|
285
|
-
path.join("node_modules", "@ethersproject"),
|
|
286
|
-
];
|
|
287
|
-
|
|
288
|
-
// Match path separators both for Windows and Unix
|
|
289
|
-
const pkgs = filename.match(/node_modules[\/\\][^\/\\]+/g);
|
|
290
|
-
|
|
291
|
-
if (pkgs === null) {
|
|
292
|
-
return false;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const errorSourcePkg = pkgs[pkgs.length - 1];
|
|
296
|
-
|
|
297
|
-
return pkgsToIgnore.includes(errorSourcePkg);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
#isHardhatFile(filename: string): boolean {
|
|
301
|
-
const nomicFoundationPath = path.join("node_modules", "@nomicfoundation");
|
|
302
|
-
const ignoredOrgPath = path.join("node_modules", "@ignored");
|
|
303
|
-
const hardhatPath = path.join("node_modules", "hardhat");
|
|
304
|
-
|
|
305
|
-
filename = filename.toLowerCase();
|
|
306
|
-
|
|
307
|
-
return (
|
|
308
|
-
filename.includes(nomicFoundationPath) ||
|
|
309
|
-
filename.includes(ignoredOrgPath) ||
|
|
310
|
-
filename.includes(hardhatPath)
|
|
311
|
-
);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
#isPackageFile(filename: string): boolean {
|
|
315
|
-
return filename.includes("node_modules");
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
#isUserProjectFile(filename: string): boolean {
|
|
319
|
-
const anonymizedUserPath = anonymizeUserPaths(filename);
|
|
320
|
-
|
|
321
|
-
return anonymizedUserPath === ANONYMIZED_PATH;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
156
|
async #anonymizeExceptions(exceptions: Exception[]): Promise<Exception[]> {
|
|
325
157
|
const anonymizedExceptions = await Promise.all(
|
|
326
158
|
exceptions.map((exception) => this.#anonymizeException(exception)),
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
import type { ServerRuntimeClientOptions, Transport } from "@sentry/core";
|
|
4
4
|
|
|
5
5
|
import os from "node:os";
|
|
6
|
-
import path from "node:path";
|
|
7
6
|
|
|
7
|
+
import { getRuntimeInfo } from "@nomicfoundation/hardhat-utils/runtime";
|
|
8
8
|
import {
|
|
9
|
+
applySdkMetadata,
|
|
9
10
|
createStackParser,
|
|
10
11
|
functionToStringIntegration,
|
|
11
12
|
initAndBind,
|
|
@@ -61,40 +62,48 @@ interface GlobalCustomSentryReporterOptions {
|
|
|
61
62
|
* errors integration.
|
|
62
63
|
*/
|
|
63
64
|
export function init(options: GlobalCustomSentryReporterOptions): void {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
65
|
+
const runtimeInfo = getRuntimeInfo();
|
|
66
|
+
const runtime = {
|
|
67
|
+
name: runtimeInfo?.runtime ?? "unknown",
|
|
68
|
+
version: runtimeInfo?.version ?? "unknown",
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const sentryOptions: ServerRuntimeClientOptions = {
|
|
72
|
+
dsn: options.dsn,
|
|
73
|
+
environment: options.environment,
|
|
74
|
+
serverName: GENERIC_SERVER_NAME,
|
|
75
|
+
release: options.release,
|
|
76
|
+
runtime,
|
|
77
|
+
initialScope: {
|
|
78
|
+
contexts: {
|
|
79
|
+
os: {
|
|
80
|
+
name: os.type(),
|
|
81
|
+
build: os.release(),
|
|
82
|
+
version: os.version(),
|
|
83
|
+
},
|
|
84
|
+
device: {
|
|
85
|
+
arch: os.arch(),
|
|
85
86
|
},
|
|
87
|
+
runtime,
|
|
86
88
|
},
|
|
87
|
-
transport: () => options.transport,
|
|
88
|
-
integrations: [
|
|
89
|
-
functionToStringIntegration(),
|
|
90
|
-
contextLinesIntegration(),
|
|
91
|
-
linkedErrorsIntegration(),
|
|
92
|
-
nodeContextIntegration(),
|
|
93
|
-
],
|
|
94
|
-
platform: process.platform,
|
|
95
|
-
stackParser: stackParserFromStackParserOptions(
|
|
96
|
-
createStackParser(nodeStackLineParser(createGetModuleFromFilename())),
|
|
97
|
-
),
|
|
98
89
|
},
|
|
90
|
+
transport: () => options.transport,
|
|
91
|
+
integrations: [
|
|
92
|
+
functionToStringIntegration(),
|
|
93
|
+
contextLinesIntegration(),
|
|
94
|
+
linkedErrorsIntegration(),
|
|
95
|
+
nodeContextIntegration(),
|
|
96
|
+
],
|
|
97
|
+
platform: "javascript",
|
|
98
|
+
stackParser: stackParserFromStackParserOptions(
|
|
99
|
+
createStackParser(nodeStackLineParser(createGetModuleFromFilename())),
|
|
100
|
+
),
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
applySdkMetadata(sentryOptions, "core");
|
|
104
|
+
|
|
105
|
+
initAndBind<ServerRuntimeClient, ServerRuntimeClientOptions>(
|
|
106
|
+
ServerRuntimeClient,
|
|
107
|
+
sentryOptions,
|
|
99
108
|
);
|
|
100
109
|
}
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
HardhatError,
|
|
3
|
-
HardhatPluginError,
|
|
4
|
-
} from "@nomicfoundation/hardhat-errors";
|
|
5
1
|
import { createDebug } from "@nomicfoundation/hardhat-utils/debug";
|
|
6
2
|
|
|
7
|
-
import {
|
|
8
|
-
ProviderError,
|
|
9
|
-
UnknownError,
|
|
10
|
-
} from "../../../builtin-plugins/network-manager/provider-errors.js";
|
|
11
|
-
import { UsingHardhat2PluginError } from "../../../using-hardhat2-plugin-errors.js";
|
|
12
3
|
import { getHardhatVersion } from "../../../utils/package.js";
|
|
13
4
|
import { isTelemetryAllowed } from "../telemetry-permissions.js";
|
|
14
5
|
|
|
@@ -110,11 +101,9 @@ class Reporter {
|
|
|
110
101
|
error: Error,
|
|
111
102
|
hint?: { unhandled?: boolean; mechanismType?: string },
|
|
112
103
|
): Promise<boolean> {
|
|
113
|
-
if (!
|
|
114
|
-
log("Error not send: this type of error should not be reported");
|
|
104
|
+
if (!this.#telemetryEnabled) {
|
|
115
105
|
return false;
|
|
116
106
|
}
|
|
117
|
-
|
|
118
107
|
const { captureException, flush } = await import("@sentry/core");
|
|
119
108
|
|
|
120
109
|
log("Capturing exception");
|
|
@@ -134,36 +123,4 @@ class Reporter {
|
|
|
134
123
|
|
|
135
124
|
return true;
|
|
136
125
|
}
|
|
137
|
-
|
|
138
|
-
async #shouldBeReported(error: Error): Promise<boolean> {
|
|
139
|
-
if (!this.#telemetryEnabled) {
|
|
140
|
-
return false;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (
|
|
144
|
-
HardhatError.isHardhatError(error) &&
|
|
145
|
-
!error.descriptor.shouldBeReported
|
|
146
|
-
) {
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (error instanceof UsingHardhat2PluginError) {
|
|
151
|
-
return false;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (HardhatPluginError.isHardhatPluginError(error)) {
|
|
155
|
-
// Don't log errors from third-party plugins
|
|
156
|
-
return false;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (
|
|
160
|
-
ProviderError.isProviderError(error) &&
|
|
161
|
-
error.code !== UnknownError.CODE
|
|
162
|
-
) {
|
|
163
|
-
// We don't report known network related errors
|
|
164
|
-
return false;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return true;
|
|
168
|
-
}
|
|
169
126
|
}
|
|
@@ -38,30 +38,22 @@ const envelope = JSON.parse(serializedEnvelope);
|
|
|
38
38
|
|
|
39
39
|
const anonymizer = new Anonymizer(configPath);
|
|
40
40
|
|
|
41
|
-
const
|
|
42
|
-
anonymizer.filterOutEventsWithExceptionsNotRaisedByHardhat(envelope);
|
|
41
|
+
const anonymizeResult = await anonymizer.anonymizeEventsFromEnvelope(envelope);
|
|
43
42
|
|
|
44
|
-
if (
|
|
45
|
-
log("
|
|
43
|
+
if (!anonymizeResult.success) {
|
|
44
|
+
log("Failed to anonymize envelope", anonymizeResult.error);
|
|
45
|
+
captureMessage(anonymizeResult.error);
|
|
46
46
|
} else {
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
try {
|
|
48
|
+
log("Sending received envelope to Sentry");
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
log("Failed to anonymize envelope", anonymizeResult.error);
|
|
52
|
-
captureMessage(anonymizeResult.error);
|
|
53
|
-
} else {
|
|
54
|
-
try {
|
|
55
|
-
log("Sending received envelope to Sentry");
|
|
50
|
+
await sendEnvelopeToSentryBackend(dsn, anonymizeResult.envelope);
|
|
56
51
|
|
|
57
|
-
|
|
52
|
+
log("Successfully sent received envelope to Sentry");
|
|
53
|
+
} catch (e) {
|
|
54
|
+
log("Failed to send received envelope to Sentry", e);
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
} catch (e) {
|
|
61
|
-
log("Failed to send received envelope to Sentry", e);
|
|
62
|
-
|
|
63
|
-
captureException(e);
|
|
64
|
-
}
|
|
56
|
+
captureException(e);
|
|
65
57
|
}
|
|
66
58
|
}
|
|
67
59
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"description": "A TypeScript Hardhat project using Node Test Runner and Viem",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"devDependencies": {
|
|
8
|
-
"hardhat": "workspace:^3.4.
|
|
8
|
+
"hardhat": "workspace:^3.4.4",
|
|
9
9
|
"@nomicfoundation/hardhat-toolbox-viem": "workspace:^5.0.4",
|
|
10
10
|
"@nomicfoundation/hardhat-ignition": "workspace:^3.1.4",
|
|
11
11
|
"@types/node": "^22.8.5",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@nomicfoundation/hardhat-network-helpers": "workspace:^3.0.7",
|
|
20
20
|
"@nomicfoundation/hardhat-node-test-runner": "workspace:^3.0.14",
|
|
21
21
|
"@nomicfoundation/hardhat-viem": "workspace:^3.0.6",
|
|
22
|
-
"@nomicfoundation/hardhat-viem-assertions": "workspace:^3.0.
|
|
22
|
+
"@nomicfoundation/hardhat-viem-assertions": "workspace:^3.0.10",
|
|
23
23
|
"@nomicfoundation/hardhat-verify": "workspace:^3.0.16",
|
|
24
24
|
"@nomicfoundation/ignition-core": "workspace:^3.1.4"
|
|
25
25
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"description": "A TypeScript Hardhat project using Mocha and Ethers.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"devDependencies": {
|
|
8
|
-
"hardhat": "workspace:^3.4.
|
|
8
|
+
"hardhat": "workspace:^3.4.4",
|
|
9
9
|
"@nomicfoundation/hardhat-toolbox-mocha-ethers": "workspace:^3.0.4",
|
|
10
10
|
"@nomicfoundation/hardhat-ethers": "workspace:^4.0.10",
|
|
11
11
|
"@nomicfoundation/hardhat-ignition": "workspace:^3.1.4",
|