Skip to content

Commit 2ac4beb

Browse files
authored
Merge pull request #6003 from NomicFoundation/network-manager-cleanup
Network manager cleanup Pt1
2 parents 7f07720 + 1f38ada commit 2ac4beb

File tree

5 files changed

+153
-142
lines changed

5 files changed

+153
-142
lines changed

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

+55-39
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {
1616
CompilerInput,
1717
CompilerOutput,
1818
} from "../../../../types/solidity/compiler-io.js";
19+
import type { JsonRpcRequestWrapperFunction } from "../network-manager.js";
1920
import type {
2021
RawTrace,
2122
SubscriptionEvent,
@@ -92,10 +93,12 @@ export async function getGlobalEdrContext(): Promise<EdrContext> {
9293
return _globalEdrContext;
9394
}
9495

95-
export type JsonRpcRequestWrapperFunction = (
96-
request: JsonRpcRequest,
97-
defaultBehavior: (r: JsonRpcRequest) => Promise<JsonRpcResponse>,
98-
) => Promise<JsonRpcResponse>;
96+
interface EdrProviderConfig {
97+
networkConfig: EdrNetworkConfig;
98+
loggerConfig?: LoggerConfig;
99+
tracingConfig?: TracingConfig;
100+
jsonRpcRequestWrapper?: JsonRpcRequestWrapperFunction;
101+
}
99102

100103
export class EdrProvider extends EventEmitter implements EthereumProvider {
101104
readonly #provider: Provider;
@@ -107,23 +110,25 @@ export class EdrProvider extends EventEmitter implements EthereumProvider {
107110
#vmTracer?: VMTracerT;
108111
#nextRequestId = 1;
109112

110-
// TODO: should take an object with all the config like the HTTP provider
111-
public static async create(
112-
config: EdrNetworkConfig,
113-
loggerConfig: LoggerConfig,
114-
tracingConfig?: TracingConfig,
115-
jsonRpcRequestWrapper?: JsonRpcRequestWrapperFunction,
116-
): Promise<EdrProvider> {
117-
const coinbase = config.coinbase ?? DEFAULT_COINBASE;
113+
/**
114+
* Creates a new instance of `EdrProvider`.
115+
*/
116+
public static async create({
117+
networkConfig,
118+
loggerConfig = { enabled: false },
119+
tracingConfig = {},
120+
jsonRpcRequestWrapper,
121+
}: EdrProviderConfig): Promise<EdrProvider> {
122+
const coinbase = networkConfig.coinbase ?? DEFAULT_COINBASE;
118123

119124
let fork;
120-
if (config.forkConfig !== undefined) {
125+
if (networkConfig.forkConfig !== undefined) {
121126
let httpHeaders: HttpHeader[] | undefined;
122-
if (config.forkConfig.httpHeaders !== undefined) {
127+
if (networkConfig.forkConfig.httpHeaders !== undefined) {
123128
httpHeaders = [];
124129

125130
for (const [name, value] of Object.entries(
126-
config.forkConfig.httpHeaders,
131+
networkConfig.forkConfig.httpHeaders,
127132
)) {
128133
httpHeaders.push({
129134
name,
@@ -133,66 +138,70 @@ export class EdrProvider extends EventEmitter implements EthereumProvider {
133138
}
134139

135140
fork = {
136-
jsonRpcUrl: config.forkConfig.jsonRpcUrl,
141+
jsonRpcUrl: networkConfig.forkConfig.jsonRpcUrl,
137142
blockNumber:
138-
config.forkConfig.blockNumber !== undefined
139-
? BigInt(config.forkConfig.blockNumber)
143+
networkConfig.forkConfig.blockNumber !== undefined
144+
? BigInt(networkConfig.forkConfig.blockNumber)
140145
: undefined,
141146
httpHeaders,
142147
};
143148
}
144149

145150
const initialDate =
146-
config.initialDate !== undefined
147-
? BigInt(Math.floor(config.initialDate.getTime() / 1000))
151+
networkConfig.initialDate !== undefined
152+
? BigInt(Math.floor(networkConfig.initialDate.getTime() / 1000))
148153
: undefined;
149154

150155
const printLineFn = loggerConfig.printLineFn ?? printLine;
151156
const replaceLastLineFn = loggerConfig.replaceLastLineFn ?? replaceLastLine;
152157

153158
const vmTraceDecoder = await createVmTraceDecoder();
154159

155-
const hardforkName = getHardforkName(config.hardfork);
160+
const hardforkName = getHardforkName(networkConfig.hardfork);
156161

157162
const context = await getGlobalEdrContext();
158163
const provider = await context.createProvider(
159-
config.chainType === "optimism"
164+
networkConfig.chainType === "optimism"
160165
? OPTIMISM_CHAIN_TYPE
161166
: GENERIC_CHAIN_TYPE, // TODO: l1 is missing here
162167
{
163168
allowBlocksWithSameTimestamp:
164-
config.allowBlocksWithSameTimestamp ?? false,
165-
allowUnlimitedContractSize: config.allowUnlimitedContractSize,
166-
bailOnCallFailure: config.throwOnCallFailures,
167-
bailOnTransactionFailure: config.throwOnTransactionFailures,
168-
blockGasLimit: BigInt(config.blockGasLimit),
169-
chainId: BigInt(config.chainId),
170-
chains: this.#convertToEdrChains(config.chains),
171-
cacheDir: config.forkCachePath,
169+
networkConfig.allowBlocksWithSameTimestamp ?? false,
170+
allowUnlimitedContractSize: networkConfig.allowUnlimitedContractSize,
171+
bailOnCallFailure: networkConfig.throwOnCallFailures,
172+
bailOnTransactionFailure: networkConfig.throwOnTransactionFailures,
173+
blockGasLimit: BigInt(networkConfig.blockGasLimit),
174+
chainId: BigInt(networkConfig.chainId),
175+
chains: this.#convertToEdrChains(networkConfig.chains),
176+
cacheDir: networkConfig.forkCachePath,
172177
coinbase: Buffer.from(coinbase.slice(2), "hex"),
173-
enableRip7212: config.enableRip7212,
178+
enableRip7212: networkConfig.enableRip7212,
174179
fork,
175180
hardfork: ethereumsjsHardforkToEdrSpecId(hardforkName),
176-
genesisAccounts: config.genesisAccounts.map((account) => {
181+
genesisAccounts: networkConfig.genesisAccounts.map((account) => {
177182
return {
178183
secretKey: account.privateKey,
179184
balance: BigInt(account.balance),
180185
};
181186
}),
182187
initialDate,
183188
initialBaseFeePerGas:
184-
config.initialBaseFeePerGas !== undefined
185-
? BigInt(config.initialBaseFeePerGas)
189+
networkConfig.initialBaseFeePerGas !== undefined
190+
? BigInt(networkConfig.initialBaseFeePerGas)
186191
: undefined,
187-
minGasPrice: config.minGasPrice,
192+
minGasPrice: networkConfig.minGasPrice,
188193
mining: {
189-
autoMine: config.automine,
190-
interval: ethereumjsIntervalMiningConfigToEdr(config.intervalMining),
194+
autoMine: networkConfig.automine,
195+
interval: ethereumjsIntervalMiningConfigToEdr(
196+
networkConfig.intervalMining,
197+
),
191198
memPool: {
192-
order: ethereumjsMempoolOrderToEdrMineOrdering(config.mempoolOrder),
199+
order: ethereumjsMempoolOrderToEdrMineOrdering(
200+
networkConfig.mempoolOrder,
201+
),
193202
},
194203
},
195-
networkId: BigInt(config.networkId),
204+
networkId: BigInt(networkConfig.networkId),
196205
},
197206
{
198207
enable: loggerConfig.enabled,
@@ -231,6 +240,13 @@ export class EdrProvider extends EventEmitter implements EthereumProvider {
231240
return edrProvider;
232241
}
233242

243+
/**
244+
* @private
245+
*
246+
* This constructor is intended for internal use only.
247+
* Use the static method {@link EdrProvider.create} to create an instance of
248+
* `EdrProvider`.
249+
*/
234250
private constructor(
235251
provider: Provider,
236252
vmTraceDecoder: VmTraceDecoder,

v-next/hardhat/src/internal/builtin-plugins/network-manager/hook-handlers/config.ts

-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ export async function extendUserConfig(
4040
const networks: Record<string, NetworkUserConfig> =
4141
extendedConfig.networks ?? {};
4242

43-
// TODO: we should address this casting when edr is implemented
4443
const localhostConfig: Omit<HttpNetworkUserConfig, "url"> = {
4544
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- This is always http
4645
...(networks.localhost as HttpNetworkUserConfig),

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

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { JsonRpcRequestWrapperFunction } from "./network-manager.js";
12
import type {
23
EthereumProvider,
34
JsonRpcRequest,
@@ -39,10 +40,14 @@ const TOO_MANY_REQUEST_STATUS = 429;
3940
const MAX_RETRIES = 6;
4041
const MAX_RETRY_WAIT_TIME_SECONDS = 5;
4142

42-
export type JsonRpcRequestWrapperFunction = (
43-
request: JsonRpcRequest,
44-
defaultBehavior: (r: JsonRpcRequest) => Promise<JsonRpcResponse>,
45-
) => Promise<JsonRpcResponse>;
43+
interface HttpProviderConfig {
44+
url: string;
45+
networkName: string;
46+
extraHeaders?: Record<string, string>;
47+
timeout: number;
48+
jsonRpcRequestWrapper?: JsonRpcRequestWrapperFunction;
49+
testDispatcher?: Dispatcher;
50+
}
4651

4752
export class HttpProvider extends EventEmitter implements EthereumProvider {
4853
readonly #url: string;
@@ -62,20 +67,16 @@ export class HttpProvider extends EventEmitter implements EthereumProvider {
6267
extraHeaders = {},
6368
timeout,
6469
jsonRpcRequestWrapper,
65-
}: {
66-
url: string;
67-
networkName: string;
68-
extraHeaders?: Record<string, string>;
69-
timeout: number;
70-
jsonRpcRequestWrapper?: JsonRpcRequestWrapperFunction;
71-
}): Promise<HttpProvider> {
70+
testDispatcher,
71+
}: HttpProviderConfig): Promise<HttpProvider> {
7272
if (!isValidUrl(url)) {
7373
throw new HardhatError(HardhatError.ERRORS.NETWORK.INVALID_URL, {
7474
value: url,
7575
});
7676
}
7777

78-
const dispatcher = await getHttpDispatcher(url, timeout);
78+
const dispatcher =
79+
testDispatcher ?? (await getHttpDispatcher(url, timeout));
7980

8081
const httpProvider = new HttpProvider(
8182
url,
@@ -95,8 +96,7 @@ export class HttpProvider extends EventEmitter implements EthereumProvider {
9596
* Use the static method {@link HttpProvider.create} to create an instance of
9697
* `HttpProvider`.
9798
*/
98-
// TODO: make the constructor private, but we need to fix the tests first
99-
constructor(
99+
private constructor(
100100
url: string,
101101
networkName: string,
102102
extraHeaders: Record<string, string>,

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

+28-31
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,27 @@ import type {
44
ChainType,
55
DefaultChainType,
66
NetworkConnection,
7+
NetworkManager,
78
} from "../../../types/network.js";
8-
import type { EthereumProvider } from "../../../types/providers.js";
9+
import type {
10+
EthereumProvider,
11+
JsonRpcRequest,
12+
JsonRpcResponse,
13+
} from "../../../types/providers.js";
914

10-
import {
11-
assertHardhatInvariant,
12-
HardhatError,
13-
} from "@ignored/hardhat-vnext-errors";
15+
import { HardhatError } from "@ignored/hardhat-vnext-errors";
1416

1517
import { EdrProvider } from "./edr/edr-provider.js";
1618
import { HttpProvider } from "./http-provider.js";
1719
import { NetworkConnectionImplementation } from "./network-connection.js";
1820
import { isNetworkConfig, validateNetworkConfig } from "./type-validation.js";
1921

20-
export class NetworkManagerImplementation {
22+
export type JsonRpcRequestWrapperFunction = (
23+
request: JsonRpcRequest,
24+
defaultBehavior: (r: JsonRpcRequest) => Promise<JsonRpcResponse>,
25+
) => Promise<JsonRpcResponse>;
26+
27+
export class NetworkManagerImplementation implements NetworkManager {
2128
readonly #defaultNetwork: string;
2229
readonly #defaultChainType: DefaultChainType;
2330
readonly #networkConfigs: Readonly<Record<string, Readonly<NetworkConfig>>>;
@@ -136,11 +143,16 @@ export class NetworkManagerImplementation {
136143
const createProvider = async (
137144
networkConnection: NetworkConnectionImplementation<ChainTypeT>,
138145
): Promise<EthereumProvider> => {
139-
assertHardhatInvariant(
140-
resolvedNetworkConfig.type === "edr" ||
141-
resolvedNetworkConfig.type === "http",
142-
`Invalid network type ${resolvedNetworkConfig.type}`,
143-
);
146+
const jsonRpcRequestWrapper: JsonRpcRequestWrapperFunction = (
147+
request,
148+
defaultBehavior,
149+
) =>
150+
hookManager.runHandlerChain(
151+
"network",
152+
"onRequest",
153+
[networkConnection, request],
154+
async (_context, _connection, req) => defaultBehavior(req),
155+
);
144156

145157
if (resolvedNetworkConfig.type === "edr") {
146158
if (
@@ -154,40 +166,25 @@ export class NetworkManagerImplementation {
154166
);
155167
}
156168

157-
return EdrProvider.create(
169+
return EdrProvider.create({
158170
// The resolvedNetworkConfig can have its chainType set to `undefined`
159171
// so we default to the default chain type here.
160-
{
172+
networkConfig: {
161173
...resolvedNetworkConfig,
162174
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions --
163175
This case is safe because we have a check above */
164176
chainType: resolvedChainType as ChainType,
165177
},
166-
{ enabled: false },
167-
{},
168-
(request, defaultBehavior) => {
169-
return hookManager.runHandlerChain(
170-
"network",
171-
"onRequest",
172-
[networkConnection, request],
173-
async (_context, _connection, req) => defaultBehavior(req),
174-
);
175-
},
176-
);
178+
jsonRpcRequestWrapper,
179+
});
177180
}
178181

179182
return HttpProvider.create({
180183
url: resolvedNetworkConfig.url,
181184
networkName: resolvedNetworkName,
182185
extraHeaders: resolvedNetworkConfig.httpHeaders,
183186
timeout: resolvedNetworkConfig.timeout,
184-
jsonRpcRequestWrapper: (request, defaultBehavior) =>
185-
hookManager.runHandlerChain(
186-
"network",
187-
"onRequest",
188-
[networkConnection, request],
189-
async (_context, _connection, req) => defaultBehavior(req),
190-
),
187+
jsonRpcRequestWrapper,
191188
});
192189
};
193190

0 commit comments

Comments
 (0)