-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5810 from NomicFoundation/move-providers-to-v3
Move V2 wrapped providers to v3
- Loading branch information
Showing
27 changed files
with
1,963 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
v-next/hardhat/src/internal/builtin-plugins/network-manager/hook-handlers/network.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import type { | ||
JsonRpcRequest, | ||
JsonRpcResponse, | ||
} from "../../../../types/providers.js"; | ||
import type { | ||
HookContext, | ||
NetworkHooks, | ||
} from "@ignored/hardhat-vnext/types/hooks"; | ||
import type { | ||
ChainType, | ||
NetworkConnection, | ||
} from "@ignored/hardhat-vnext/types/network"; | ||
|
||
import { JsonRpcRequestModifier } from "../json-rpc-request-modifiers/json-rpc-request-modifier.js"; | ||
|
||
export default async (): Promise<Partial<NetworkHooks>> => { | ||
// This map is necessary because Hardhat V3 supports multiple network connections, requiring us to track them | ||
// to apply the appropriate modifiers to each request. | ||
// When a connection is closed, it is removed from the map. Refer to "closeConnection" at the end of the file. | ||
const jsonRpcRequestModifiers: Map<number, JsonRpcRequestModifier> = | ||
new Map(); | ||
|
||
const handlers: Partial<NetworkHooks> = { | ||
async onRequest<ChainTypeT extends ChainType | string>( | ||
context: HookContext, | ||
networkConnection: NetworkConnection<ChainTypeT>, | ||
jsonRpcRequest: JsonRpcRequest, | ||
next: ( | ||
nextContext: HookContext, | ||
nextNetworkConnection: NetworkConnection<ChainTypeT>, | ||
nextJsonRpcRequest: JsonRpcRequest, | ||
) => Promise<JsonRpcResponse>, | ||
) { | ||
let jsonRpcRequestModifier = jsonRpcRequestModifiers.get( | ||
networkConnection.id, | ||
); | ||
|
||
if (jsonRpcRequestModifier === undefined) { | ||
jsonRpcRequestModifier = new JsonRpcRequestModifier(networkConnection); | ||
|
||
jsonRpcRequestModifiers.set( | ||
networkConnection.id, | ||
jsonRpcRequestModifier, | ||
); | ||
} | ||
|
||
const newJsonRpcRequest = | ||
await jsonRpcRequestModifier.createModifiedJsonRpcRequest( | ||
jsonRpcRequest, | ||
); | ||
|
||
return next(context, networkConnection, newJsonRpcRequest); | ||
}, | ||
|
||
async closeConnection<ChainTypeT extends ChainType | string>( | ||
context: HookContext, | ||
networkConnection: NetworkConnection<ChainTypeT>, | ||
next: ( | ||
nextContext: HookContext, | ||
nextNetworkConnection: NetworkConnection<ChainTypeT>, | ||
) => Promise<void>, | ||
): Promise<void> { | ||
if (jsonRpcRequestModifiers.has(networkConnection.id) === true) { | ||
jsonRpcRequestModifiers.delete(networkConnection.id); | ||
} | ||
|
||
return next(context, networkConnection); | ||
}, | ||
}; | ||
|
||
return handlers; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
...builtin-plugins/network-manager/json-rpc-request-modifiers/chain-id/chain-id-validator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import type { EthereumProvider } from "../../../../../types/providers.js"; | ||
|
||
import { HardhatError } from "@ignored/hardhat-vnext-errors"; | ||
|
||
import { ChainId } from "./chain-id.js"; | ||
|
||
/** | ||
* This class extends `ChainId` to validate that the current provider's chain ID matches | ||
* an expected value. If the actual chain ID differs from the expected one, it throws a | ||
* HardhatError to signal a network configuration mismatch. Once validated, further checks | ||
* are skipped to avoid redundant validations. | ||
*/ | ||
export class ChainIdValidator extends ChainId { | ||
readonly #expectedChainId: number; | ||
|
||
#alreadyValidated = false; | ||
readonly #chainId: number | undefined; | ||
|
||
constructor(provider: EthereumProvider, expectedChainId: number) { | ||
super(provider); | ||
this.#expectedChainId = expectedChainId; | ||
} | ||
|
||
public async validate(): Promise<void> { | ||
if (!this.#alreadyValidated) { | ||
const actualChainId = await this.getChainId(); | ||
|
||
if (actualChainId !== this.#expectedChainId) { | ||
throw new HardhatError( | ||
HardhatError.ERRORS.NETWORK.INVALID_GLOBAL_CHAIN_ID, | ||
{ | ||
configChainId: this.#expectedChainId, | ||
connectionChainId: actualChainId, | ||
}, | ||
); | ||
} | ||
|
||
this.#alreadyValidated = true; | ||
} | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
.../internal/builtin-plugins/network-manager/json-rpc-request-modifiers/chain-id/chain-id.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import type { EthereumProvider } from "../../../../../types/providers.js"; | ||
|
||
import { assertHardhatInvariant } from "@ignored/hardhat-vnext-errors"; | ||
import { | ||
hexStringToNumber, | ||
isHexStringPrefixed, | ||
} from "@ignored/hardhat-vnext-utils/hex"; | ||
|
||
/** | ||
* This class is responsible for retrieving the chain ID of the network. | ||
* It uses the provider to fetch the chain ID via two methods: 'eth_chainId' and, | ||
* as a fallback, 'net_version' if the first one fails. The chain ID is cached | ||
* after being retrieved to avoid redundant requests. | ||
*/ | ||
export abstract class ChainId { | ||
protected readonly provider: EthereumProvider; | ||
|
||
#chainId: number | undefined; | ||
|
||
constructor(provider: EthereumProvider) { | ||
this.provider = provider; | ||
} | ||
|
||
protected async getChainId(): Promise<number> { | ||
if (this.#chainId === undefined) { | ||
try { | ||
this.#chainId = await this.getChainIdFromEthChainId(); | ||
} catch { | ||
// If eth_chainId fails we default to net_version | ||
this.#chainId = await this.#getChainIdFromEthNetVersion(); | ||
} | ||
} | ||
|
||
return this.#chainId; | ||
} | ||
|
||
protected async getChainIdFromEthChainId(): Promise<number> { | ||
const id = await this.provider.request({ | ||
method: "eth_chainId", | ||
}); | ||
|
||
assertHardhatInvariant(typeof id === "string", "id should be a string"); | ||
|
||
return hexStringToNumber(id); | ||
} | ||
|
||
async #getChainIdFromEthNetVersion(): Promise<number> { | ||
const id = await this.provider.request({ | ||
method: "net_version", | ||
}); | ||
|
||
assertHardhatInvariant(typeof id === "string", "id should be a string"); | ||
|
||
// There's a node returning this as decimal instead of QUANTITY. | ||
// TODO: from V2 - Document here which node does that | ||
return isHexStringPrefixed(id) ? hexStringToNumber(id) : parseInt(id, 10); | ||
} | ||
} |
Oops, something went wrong.