@@ -7,6 +7,9 @@ import type {
7
7
import type { IncomingMessage , ServerResponse } from "node:http" ;
8
8
import type WebSocket from "ws" ;
9
9
10
+ import { ensureError } from "@nomicfoundation/hardhat-utils/error" ;
11
+ import { isObject } from "@nomicfoundation/hardhat-utils/lang" ;
12
+
10
13
import {
11
14
isJsonRpcRequest ,
12
15
isJsonRpcResponse ,
@@ -36,10 +39,11 @@ export class JsonRpcHandler {
36
39
return ;
37
40
}
38
41
39
- let jsonHttpRequest : any ;
42
+ let jsonHttpRequest : unknown ;
40
43
try {
41
44
jsonHttpRequest = await _readJsonHttpRequest ( req ) ;
42
45
} catch ( error ) {
46
+ ensureError ( error ) ;
43
47
this . #sendResponse( res , _handleError ( error ) ) ;
44
48
return ;
45
49
}
@@ -48,7 +52,9 @@ export class JsonRpcHandler {
48
52
// the following code block could be safely removed.
49
53
if ( Array . isArray ( jsonHttpRequest ) ) {
50
54
const responses = await Promise . all (
51
- jsonHttpRequest . map ( ( singleReq : any ) => this . #handleRequest( singleReq ) ) ,
55
+ jsonHttpRequest . map ( ( singleReq : unknown ) =>
56
+ this . #handleRequest( singleReq ) ,
57
+ ) ,
52
58
) ;
53
59
54
60
this . #sendResponse( res , responses ) ;
@@ -80,6 +86,7 @@ export class JsonRpcHandler {
80
86
} ) ,
81
87
) ;
82
88
} catch ( error ) {
89
+ ensureError ( error ) ;
83
90
_handleError ( error ) ;
84
91
}
85
92
} ;
@@ -100,6 +107,7 @@ export class JsonRpcHandler {
100
107
)
101
108
: await this . #handleWsRequest( rpcReq , subscriptions ) ;
102
109
} catch ( error ) {
110
+ ensureError ( error ) ;
103
111
rpcResp = _handleError ( error ) ;
104
112
}
105
113
@@ -142,28 +150,36 @@ export class JsonRpcHandler {
142
150
res . end ( JSON . stringify ( rpcResp ) ) ;
143
151
}
144
152
145
- async #handleRequest( req : JsonRpcRequest ) : Promise < JsonRpcResponse > {
146
- req . params = req . params ?? [ ] ;
153
+ async #handleRequest( payload : unknown ) : Promise < JsonRpcResponse > {
154
+ if ( ! isObject ( payload ) ) {
155
+ return _handleError ( new InvalidRequestError ( ) ) ;
156
+ }
157
+
158
+ const maybeReq = {
159
+ ...payload ,
160
+ params : payload . params ?? [ ] ,
161
+ } ;
147
162
148
- if ( ! isJsonRpcRequest ( req ) ) {
163
+ if ( ! isJsonRpcRequest ( maybeReq ) ) {
149
164
return _handleError ( new InvalidRequestError ( ) ) ;
150
165
}
151
166
152
- const rpcReq : JsonRpcRequest = req ;
167
+ const rpcReq : JsonRpcRequest = maybeReq ;
153
168
let rpcResp : JsonRpcResponse | undefined ;
154
169
155
170
try {
156
171
const result = await this . #provider. request ( {
157
- method : req . method ,
158
- params : req . params ,
172
+ method : rpcReq . method ,
173
+ params : rpcReq . params ,
159
174
} ) ;
160
175
161
176
rpcResp = {
162
177
jsonrpc : "2.0" ,
163
- id : req . id ,
178
+ id : rpcReq . id ,
164
179
result,
165
180
} ;
166
181
} catch ( error ) {
182
+ ensureError ( error ) ;
167
183
rpcResp = _handleError ( error ) ;
168
184
}
169
185
@@ -195,8 +211,8 @@ export class JsonRpcHandler {
195
211
}
196
212
}
197
213
198
- const _readJsonHttpRequest = async ( req : IncomingMessage ) : Promise < any > => {
199
- let json ;
214
+ const _readJsonHttpRequest = async ( req : IncomingMessage ) : Promise < unknown > => {
215
+ let json : unknown ;
200
216
201
217
try {
202
218
const bytes : number [ ] = [ ] ;
@@ -233,26 +249,7 @@ const _readWsRequest = (msg: string): JsonRpcRequest | JsonRpcRequest[] => {
233
249
return json ;
234
250
} ;
235
251
236
- const _handleError = ( error : any ) : JsonRpcResponse => {
237
- // extract the relevant fields from the error before wrapping it
238
- let txHash : string | undefined ;
239
- let returnData : string | undefined ;
240
-
241
- if ( error . transactionHash !== undefined ) {
242
- txHash = error . transactionHash ;
243
- }
244
- if ( error . data !== undefined ) {
245
- if ( error . data . data !== undefined ) {
246
- returnData = error . data . data ;
247
- } else {
248
- returnData = error . data ;
249
- }
250
-
251
- if ( txHash === undefined && error . data . transactionHash !== undefined ) {
252
- txHash = error . data . transactionHash ;
253
- }
254
- }
255
-
252
+ const _handleError = ( error : Error ) : JsonRpcResponse => {
256
253
// In case of non-hardhat error, treat it as internal and associate the appropriate error code.
257
254
if ( ! ProviderError . isProviderError ( error ) ) {
258
255
error = new InternalError ( undefined , error ) ;
@@ -262,24 +259,46 @@ const _handleError = (error: any): JsonRpcResponse => {
262
259
jsonrpc : "2.0" ,
263
260
id : null ,
264
261
error : {
265
- code : error . code ,
262
+ code :
263
+ "code" in error && typeof error . code === "number"
264
+ ? error . code
265
+ : InternalError . CODE ,
266
266
message : error . message ,
267
+ data : {
268
+ message : error . message ,
269
+ txHash : extractTxHash ( error ) ,
270
+ data : extractReturnData ( error ) ,
271
+ } ,
267
272
} ,
268
273
} ;
269
274
270
- const data : any = {
271
- message : error . message ,
272
- } ;
275
+ return response ;
276
+ } ;
273
277
274
- if ( txHash !== undefined ) {
275
- data . txHash = txHash ;
278
+ function extractTxHash ( error : Error ) : string | undefined {
279
+ if ( "transactionHash" in error && typeof error . transactionHash === "string" ) {
280
+ return error . transactionHash ;
281
+ }
282
+
283
+ if (
284
+ "data" in error &&
285
+ isObject ( error . data ) &&
286
+ typeof error . data . transactionHash === "string"
287
+ ) {
288
+ return error . data . transactionHash ;
276
289
}
290
+ }
277
291
278
- if ( returnData !== undefined ) {
279
- data . data = returnData ;
292
+ function extractReturnData ( error : Error ) : string | undefined {
293
+ if ( ! ( "data" in error ) ) {
294
+ return undefined ;
280
295
}
281
296
282
- response . error . data = data ;
297
+ if ( typeof error . data === "string" ) {
298
+ return error . data ;
299
+ }
283
300
284
- return response ;
285
- } ;
301
+ if ( isObject ( error . data ) && typeof error . data . data === "string" ) {
302
+ return error . data . data ;
303
+ }
304
+ }
0 commit comments