Skip to content

Commit 1e10559

Browse files
committed
feat: cleanup provider and stack traces logic
1 parent 24a8e04 commit 1e10559

File tree

8 files changed

+149
-169
lines changed

8 files changed

+149
-169
lines changed

v-next/hardhat/src/internal/builtin-plugins/network-manager/edr/edr-provider.ts

+54-72
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import type { LoggerConfig } from "./types/logger.js";
33
import type { TracingConfig } from "./types/node-types.js";
44
import type { EdrNetworkConfig } from "../../../../types/config.js";
55
import type {
6-
EthSubscription,
7-
FailedJsonRpcResponse,
86
JsonRpcResponse,
97
RequestArguments,
108
SuccessfulJsonRpcResponse,
@@ -15,7 +13,6 @@ import type {
1513
SubscriptionEvent,
1614
Response,
1715
Provider,
18-
DebugTraceResult,
1916
ProviderConfig,
2017
} from "@ignored/edr-optimism";
2118

@@ -25,25 +22,20 @@ import {
2522
l1GenesisState,
2623
l1HardforkFromString,
2724
} from "@ignored/edr-optimism";
25+
import { assertHardhatInvariant } from "@ignored/hardhat-vnext-errors";
2826
import { toSeconds } from "@ignored/hardhat-vnext-utils/date";
27+
import { numberToHexString } from "@ignored/hardhat-vnext-utils/hex";
2928
import { deepEqual } from "@ignored/hardhat-vnext-utils/lang";
3029
import debug from "debug";
3130

32-
import {
33-
EDR_NETWORK_RESET_EVENT,
34-
EDR_NETWORK_REVERT_SNAPSHOT_EVENT,
35-
} from "../../../constants.js";
31+
import { EDR_NETWORK_REVERT_SNAPSHOT_EVENT } from "../../../constants.js";
3632
import { DEFAULT_HD_ACCOUNTS_CONFIG_PARAMS } from "../accounts/constants.js";
3733
import { BaseProvider } from "../base-provider.js";
3834
import { getJsonRpcRequest, isFailedJsonRpcResponse } from "../json-rpc.js";
3935

4036
import { getGlobalEdrContext } from "./edr-context.js";
41-
import {
42-
InvalidArgumentsError,
43-
InvalidInputError,
44-
ProviderError,
45-
} from "./errors.js";
46-
import { encodeSolidityStackTrace } from "./stack-traces/stack-trace-solidity-errors.js";
37+
import { InvalidArgumentsError, ProviderError } from "./errors.js";
38+
import { createSolidityErrorWithStackTrace } from "./stack-traces/stack-trace-solidity-errors.js";
4739
import { clientVersion } from "./utils/client-version.js";
4840
import { ConsoleLogger } from "./utils/console-logger.js";
4941
import {
@@ -55,6 +47,7 @@ import {
5547
hardhatChainsToEdrChains,
5648
hardhatForkingConfigToEdrForkConfig,
5749
hardhatChainTypeToEdrChainType,
50+
isDebugTraceResult,
5851
} from "./utils/convert-to-edr.js";
5952
import { printLine, replaceLastLine } from "./utils/logger.js";
6053

@@ -177,27 +170,22 @@ export class EdrProvider extends BaseProvider {
177170
super();
178171

179172
this.#provider = provider;
180-
181173
this.#jsonRpcRequestWrapper = jsonRpcRequestWrapper;
182174
}
183175

184-
public async request(args: RequestArguments): Promise<unknown> {
185-
if (args.params !== undefined && !Array.isArray(args.params)) {
186-
// eslint-disable-next-line no-restricted-syntax -- TODO: review whether this should be a HH error
187-
throw new InvalidInputError(
188-
"Hardhat Network doesn't support JSON-RPC params sent as an object",
189-
);
190-
}
191-
192-
const params = args.params ?? [];
176+
public async request(
177+
requestArguments: RequestArguments,
178+
): Promise<SuccessfulJsonRpcResponse["result"]> {
179+
const { method, params } = requestArguments;
193180

194181
const jsonRpcRequest = getJsonRpcRequest(
195182
this.#nextRequestId++,
196-
args.method,
183+
method,
197184
params,
198185
);
199186

200187
let jsonRpcResponse: JsonRpcResponse;
188+
201189
if (this.#jsonRpcRequestWrapper !== undefined) {
202190
jsonRpcResponse = await this.#jsonRpcRequestWrapper(
203191
jsonRpcRequest,
@@ -216,12 +204,6 @@ export class EdrProvider extends BaseProvider {
216204
jsonRpcResponse = await this.#handleEdrResponse(edrResponse);
217205
}
218206

219-
if (args.method === "hardhat_reset") {
220-
this.emit(EDR_NETWORK_RESET_EVENT);
221-
} else if (args.method === "evm_revert") {
222-
this.emit(EDR_NETWORK_REVERT_SNAPSHOT_EVENT);
223-
}
224-
225207
// this can only happen if a wrapper doesn't call the default
226208
// behavior as the default throws on FailedJsonRpcResponse
227209
if (isFailedJsonRpcResponse(jsonRpcResponse)) {
@@ -235,19 +217,27 @@ export class EdrProvider extends BaseProvider {
235217
throw error;
236218
}
237219

220+
if (jsonRpcRequest.method === "evm_revert") {
221+
this.emit(EDR_NETWORK_REVERT_SNAPSHOT_EVENT);
222+
}
223+
238224
// Override EDR version string with Hardhat version string with EDR backend,
239225
// e.g. `HardhatNetwork/2.19.0/@ignored/edr-optimism/0.2.0-dev`
240-
if (args.method === "web3_clientVersion") {
241-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- TODO
242-
return clientVersion(jsonRpcResponse.result as string);
226+
if (jsonRpcRequest.method === "web3_clientVersion") {
227+
assertHardhatInvariant(
228+
typeof jsonRpcResponse.result === "string",
229+
"Invalid client version response",
230+
);
231+
return clientVersion(jsonRpcResponse.result);
243232
} else if (
244-
args.method === "debug_traceTransaction" ||
245-
args.method === "debug_traceCall"
233+
jsonRpcRequest.method === "debug_traceTransaction" ||
234+
jsonRpcRequest.method === "debug_traceCall"
246235
) {
247-
return edrRpcDebugTraceToHardhat(
248-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- TODO
249-
jsonRpcResponse.result as DebugTraceResult,
236+
assertHardhatInvariant(
237+
isDebugTraceResult(jsonRpcResponse.result),
238+
"Invalid debug trace response",
250239
);
240+
return edrRpcDebugTraceToHardhat(jsonRpcResponse.result);
251241
} else {
252242
return jsonRpcResponse.result;
253243
}
@@ -257,10 +247,6 @@ export class EdrProvider extends BaseProvider {
257247
// TODO: what needs cleaned up?
258248
}
259249

260-
#isErrorResponse(response: any): response is FailedJsonRpcResponse {
261-
return typeof response.error !== "undefined";
262-
}
263-
264250
async #handleEdrResponse(
265251
edrResponse: Response,
266252
): Promise<SuccessfulJsonRpcResponse> {
@@ -272,7 +258,8 @@ export class EdrProvider extends BaseProvider {
272258
jsonRpcResponse = edrResponse.data;
273259
}
274260

275-
if (this.#isErrorResponse(jsonRpcResponse)) {
261+
if (isFailedJsonRpcResponse(jsonRpcResponse)) {
262+
const responseError = jsonRpcResponse.error;
276263
let error;
277264

278265
let stackTrace: SolidityStackTrace | null = null;
@@ -283,66 +270,61 @@ export class EdrProvider extends BaseProvider {
283270
}
284271

285272
if (stackTrace !== null) {
286-
error = encodeSolidityStackTrace(
287-
jsonRpcResponse.error.message,
273+
// Pass data and transaction hash from the original error
274+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
275+
-- If we have a stack trace, we know that the json rpc response data
276+
is an object with the data and transactionHash fields */
277+
const responseErrorData = responseError.data as {
278+
data?: string;
279+
transactionHash?: string;
280+
};
281+
282+
error = createSolidityErrorWithStackTrace(
283+
responseError.message,
288284
stackTrace,
285+
responseErrorData?.data,
286+
responseErrorData?.transactionHash,
289287
);
290-
291-
// Pass data and transaction hash from the original error
292-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- TODO: can we improve this `any
293-
(error as any).data =
294-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- TODO: can we improve this `any
295-
(jsonRpcResponse as any).error.data?.data ?? undefined;
296-
297-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- TODO: can we improve this `any`
298-
(error as any).transactionHash =
299-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- TODO: this really needs fixed
300-
(jsonRpcResponse as any).error.data?.transactionHash ?? undefined;
301288
} else {
302-
if (jsonRpcResponse.error.code === InvalidArgumentsError.CODE) {
303-
error = new InvalidArgumentsError(jsonRpcResponse.error.message);
304-
} else {
305-
error = new ProviderError(
306-
jsonRpcResponse.error.message,
307-
jsonRpcResponse.error.code,
308-
);
309-
}
310-
error.data = jsonRpcResponse.error.data;
289+
error =
290+
responseError.code === InvalidArgumentsError.CODE
291+
? new InvalidArgumentsError(responseError.message)
292+
: new ProviderError(responseError.message, responseError.code);
293+
error.data = responseError.data;
311294
}
312295

313-
// eslint-disable-next-line no-restricted-syntax -- we may throw non-Hardaht errors inside of an EthereumProvider
296+
/* eslint-disable-next-line no-restricted-syntax -- we may throw
297+
non-Hardaht errors inside of an EthereumProvider */
314298
throw error;
315299
}
316300

317301
return jsonRpcResponse;
318302
}
319303

320304
public onSubscriptionEvent(event: SubscriptionEvent): void {
321-
const subscription = `0x${event.filterId.toString(16)}`;
305+
const subscription = numberToHexString(event.filterId);
322306
const results = Array.isArray(event.result) ? event.result : [event.result];
323307
for (const result of results) {
324308
this.#emitLegacySubscriptionEvent(subscription, result);
325309
this.#emitEip1193SubscriptionEvent(subscription, result);
326310
}
327311
}
328312

329-
#emitLegacySubscriptionEvent(subscription: string, result: any) {
313+
#emitLegacySubscriptionEvent(subscription: string, result: unknown) {
330314
this.emit("notification", {
331315
subscription,
332316
result,
333317
});
334318
}
335319

336320
#emitEip1193SubscriptionEvent(subscription: string, result: unknown) {
337-
const message: EthSubscription = {
321+
this.emit("message", {
338322
type: "eth_subscription",
339323
data: {
340324
subscription,
341325
result,
342326
},
343-
};
344-
345-
this.emit("message", message);
327+
});
346328
}
347329
}
348330

v-next/hardhat/src/internal/builtin-plugins/network-manager/edr/errors.ts

-8
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,6 @@ export class InternalError extends ProviderError {
8888
}
8989
}
9090

91-
export class InvalidInputError extends ProviderError {
92-
public static readonly CODE = -32000;
93-
94-
constructor(message: string, parent?: Error) {
95-
super(message, InvalidInputError.CODE, parent);
96-
}
97-
}
98-
9991
export class TransactionExecutionError extends ProviderError {
10092
public static readonly CODE = -32003;
10193

0 commit comments

Comments
 (0)