diff --git a/.changeset/fast-bees-smash.md b/.changeset/fast-bees-smash.md new file mode 100644 index 00000000000..df4639a5bde --- /dev/null +++ b/.changeset/fast-bees-smash.md @@ -0,0 +1,5 @@ +--- +"hardhat": minor +--- + +Add `getOrCreate` to the network API diff --git a/.changeset/purple-forks-write.md b/.changeset/purple-forks-write.md new file mode 100644 index 00000000000..2b536addc12 --- /dev/null +++ b/.changeset/purple-forks-write.md @@ -0,0 +1,19 @@ +--- +"@nomicfoundation/hardhat-ethers-chai-matchers": patch +"@nomicfoundation/hardhat-toolbox-mocha-ethers": patch +"@nomicfoundation/hardhat-ignition-ethers": patch +"@nomicfoundation/hardhat-network-helpers": patch +"@nomicfoundation/hardhat-viem-assertions": patch +"@nomicfoundation/hardhat-ignition-viem": patch +"@nomicfoundation/hardhat-toolbox-viem": patch +"@nomicfoundation/hardhat-ignition": patch +"@nomicfoundation/hardhat-errors": patch +"@nomicfoundation/hardhat-ethers": patch +"@nomicfoundation/hardhat-ledger": patch +"@nomicfoundation/hardhat-verify": patch +"@nomicfoundation/ignition-core": patch +"@nomicfoundation/hardhat-viem": patch +"hardhat": patch +--- + +Deprecate the `hre.network.connect()` method in favour of `hre.network.create()`, exactly the same method but more clearly indicating that it will create a new connection. diff --git a/.peer-bumps.json b/.peer-bumps.json index a8d693abdab..3e7787d0100 100644 --- a/.peer-bumps.json +++ b/.peer-bumps.json @@ -21,6 +21,66 @@ "package": "@nomicfoundation/hardhat-ignition-ethers", "peer": "@nomicfoundation/hardhat-ignition", "reason": "The usage of the new `getUserInterruptionsHandlers` helper from `@nomicfoundation/hardhat-ignition/helpers`" + }, + { + "package": "@nomicfoundation/hardhat-ignition", + "peer": "hardhat", + "reason": "Switched from deprecated `hre.network.connect()` to new `hre.network.create()` in deploy, track-tx, transactions, and verify tasks" + }, + { + "package": "@nomicfoundation/hardhat-verify", + "peer": "hardhat", + "reason": "Switched from deprecated `network.connect()` to new `network.create()` in verification logic and updated API docs" + }, + { + "package": "@nomicfoundation/hardhat-ethers-chai-matchers", + "peer": "hardhat", + "reason": "Conservative bump for `connect()` deprecation and `create()`/`getOrCreate()` network API changes" + }, + { + "package": "@nomicfoundation/hardhat-toolbox-mocha-ethers", + "peer": "hardhat", + "reason": "Conservative bump for `connect()` deprecation and `create()`/`getOrCreate()` network API changes" + }, + { + "package": "@nomicfoundation/hardhat-ignition-ethers", + "peer": "hardhat", + "reason": "Conservative bump for `connect()` deprecation and `create()`/`getOrCreate()` network API changes" + }, + { + "package": "@nomicfoundation/hardhat-network-helpers", + "peer": "hardhat", + "reason": "Conservative bump for `connect()` deprecation and `create()`/`getOrCreate()` network API changes" + }, + { + "package": "@nomicfoundation/hardhat-viem-assertions", + "peer": "hardhat", + "reason": "Conservative bump for `connect()` deprecation and `create()`/`getOrCreate()` network API changes" + }, + { + "package": "@nomicfoundation/hardhat-ignition-viem", + "peer": "hardhat", + "reason": "Conservative bump for `connect()` deprecation and `create()`/`getOrCreate()` network API changes" + }, + { + "package": "@nomicfoundation/hardhat-toolbox-viem", + "peer": "hardhat", + "reason": "Conservative bump for `connect()` deprecation and `create()`/`getOrCreate()` network API changes" + }, + { + "package": "@nomicfoundation/hardhat-ethers", + "peer": "hardhat", + "reason": "Conservative bump for `connect()` deprecation and `create()`/`getOrCreate()` network API changes" + }, + { + "package": "@nomicfoundation/hardhat-ledger", + "peer": "hardhat", + "reason": "Conservative bump for `connect()` deprecation and `create()`/`getOrCreate()` network API changes" + }, + { + "package": "@nomicfoundation/hardhat-viem", + "peer": "hardhat", + "reason": "Conservative bump for `connect()` deprecation and `create()`/`getOrCreate()` network API changes" } ] } diff --git a/packages/example-project/hardhat.config.ts b/packages/example-project/hardhat.config.ts index d97dce3d550..af827851601 100644 --- a/packages/example-project/hardhat.config.ts +++ b/packages/example-project/hardhat.config.ts @@ -94,7 +94,7 @@ const printConfig = task("config", "Print the config") const printAccounts = task("accounts", "Print the accounts") .setAction(async () => ({ default: async ({}, hre) => { - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); console.log(await provider.request({ method: "eth_accounts" })); }, })) diff --git a/packages/example-project/scripts/demo-trace-output.ts b/packages/example-project/scripts/demo-trace-output.ts index 42fed1f671c..b7f5b09ed3a 100644 --- a/packages/example-project/scripts/demo-trace-output.ts +++ b/packages/example-project/scripts/demo-trace-output.ts @@ -23,8 +23,8 @@ import hre from "hardhat"; // ═══════════════════════════════════════════════════════════════════════ // Setup: two connections to two independent EDR-simulated networks // ═══════════════════════════════════════════════════════════════════════ -const connA = await hre.network.connect("default"); -const connB = await hre.network.connect("node"); +const connA = await hre.network.create("default"); +const connB = await hre.network.create("node"); const [counterA, counterB, revertContract] = await Promise.all([ connA.viem.deployContract("Counter", []), diff --git a/packages/example-project/scripts/deploy-rocket-from-script.ts b/packages/example-project/scripts/deploy-rocket-from-script.ts index d01b6d73e19..7941f83cb89 100644 --- a/packages/example-project/scripts/deploy-rocket-from-script.ts +++ b/packages/example-project/scripts/deploy-rocket-from-script.ts @@ -2,7 +2,7 @@ import hre from "hardhat"; import apolloModule from "../ignition/modules/Apollo.js"; -const { ignition } = await hre.network.connect(); +const { ignition } = await hre.network.create(); const { apollo } = await ignition.deploy(apolloModule); diff --git a/packages/example-project/scripts/hardhat-ethers.ts b/packages/example-project/scripts/hardhat-ethers.ts index 9a8929c5327..369c57e7423 100644 --- a/packages/example-project/scripts/hardhat-ethers.ts +++ b/packages/example-project/scripts/hardhat-ethers.ts @@ -5,7 +5,7 @@ import hre from "hardhat"; -const { ethers } = await hre.network.connect(); +const { ethers } = await hre.network.create(); // ethers functionalities ethers.isAddress("0x1234567890123456789012345678901234567890"); diff --git a/packages/example-project/scripts/ledger.ts b/packages/example-project/scripts/ledger.ts index c7ba4162c8e..ce2c8243251 100644 --- a/packages/example-project/scripts/ledger.ts +++ b/packages/example-project/scripts/ledger.ts @@ -3,7 +3,7 @@ import assert from "node:assert"; const BALANCE_TO_SEND = 1000000000000000000n; -const { provider, ethers } = await hre.network.connect("edrOp"); +const { provider, ethers } = await hre.network.create("edrOp"); const signers = await ethers.getSigners(); diff --git a/packages/example-project/scripts/network-helpers.ts b/packages/example-project/scripts/network-helpers.ts index dd063ef9793..5f209401772 100644 --- a/packages/example-project/scripts/network-helpers.ts +++ b/packages/example-project/scripts/network-helpers.ts @@ -5,6 +5,6 @@ import hre from "hardhat"; -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.mine(); diff --git a/packages/example-project/scripts/send-op-tx-viem.ts b/packages/example-project/scripts/send-op-tx-viem.ts index e6428ff14c7..9bc4d147555 100644 --- a/packages/example-project/scripts/send-op-tx-viem.ts +++ b/packages/example-project/scripts/send-op-tx-viem.ts @@ -3,7 +3,7 @@ import { network } from "hardhat"; async function sendL2Transaction(networkConfigName: string) { console.log("Sending transaction using network", networkConfigName); - const { viem, networkConfig } = await network.connect({ + const { viem, networkConfig } = await network.create({ network: networkConfigName, chainType: "op", }); diff --git a/packages/example-project/scripts/send-op-tx.ts b/packages/example-project/scripts/send-op-tx.ts index 2326bd1a9e1..347ee9b78d0 100644 --- a/packages/example-project/scripts/send-op-tx.ts +++ b/packages/example-project/scripts/send-op-tx.ts @@ -1,6 +1,6 @@ import { network } from "hardhat"; -const { provider } = await network.connect({ +const { provider } = await network.create({ network: "op", chainType: "op", }); diff --git a/packages/example-project/scripts/viem-plugin-example.ts b/packages/example-project/scripts/viem-plugin-example.ts index b2753bb954b..b50a006d99c 100644 --- a/packages/example-project/scripts/viem-plugin-example.ts +++ b/packages/example-project/scripts/viem-plugin-example.ts @@ -3,7 +3,7 @@ import { parseEther } from "viem"; async function testL2Extensions() { // This network connection has access to an optimism-specific viem api - const optimism = await hre.network.connect({ + const optimism = await hre.network.create({ network: "localhost", chainType: "op", }); @@ -12,7 +12,7 @@ async function testL2Extensions() { console.log("L1 base fee:", l1BaseFee); // This one doesn't - const mainnet = await hre.network.connect({ + const mainnet = await hre.network.create({ network: "localhost", chainType: "l1", }); @@ -26,7 +26,7 @@ async function testL2Extensions() { } async function testClients() { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const publicClient = await networkConnection.viem.getPublicClient(); const [fromWalletClient, toWalletClient] = @@ -72,7 +72,7 @@ async function testClients() { } async function testContracts() { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const counter = await networkConnection.viem.deployContract("Counter"); console.log("Deployed contract at address", counter.address); diff --git a/packages/example-project/test/mocha/mocha-test.ts b/packages/example-project/test/mocha/mocha-test.ts index e42214c4c03..19f8fd83f78 100644 --- a/packages/example-project/test/mocha/mocha-test.ts +++ b/packages/example-project/test/mocha/mocha-test.ts @@ -15,7 +15,7 @@ describe("Mocha test", () => { describe("Mocha test with chai-matchers", () => { before(async () => { - await hre.network.connect(); + await hre.network.create(); }); it("should import variables from the chai-matchers package", () => { @@ -30,7 +30,7 @@ describe("Mocha test with chai-matchers", () => { describe("Rocket test", () => { it("should launch the Apollo 11 rocket", async () => { - const connection = await hre.network.connect(); + const connection = await hre.network.create(); const Rocket = await connection.ethers.getContractFactory("Rocket"); const rocket = await Rocket.deploy("Apollo 11"); @@ -43,7 +43,7 @@ describe("Rocket test", () => { describe("Matchers without automining", () => { it("emit should wait for the tx to be mined", async () => { - const { ethers, provider } = await hre.network.connect(); + const { ethers, provider } = await hre.network.create(); const Rocket = await ethers.getContractFactory("Rocket"); const rocket = await Rocket.deploy("Apollo 11"); @@ -62,7 +62,7 @@ describe("Matchers without automining", () => { }); it("revert should wait for the tx to be mined", async () => { - const { ethers, provider } = await hre.network.connect(); + const { ethers, provider } = await hre.network.create(); const FailingContract = await ethers.getContractFactory("FailingContract"); const failing = await FailingContract.deploy(); diff --git a/packages/example-project/test/node/example-test-of-assertions.ts b/packages/example-project/test/node/example-test-of-assertions.ts index 0b4a72adc79..22b2a8df07a 100644 --- a/packages/example-project/test/node/example-test-of-assertions.ts +++ b/packages/example-project/test/node/example-test-of-assertions.ts @@ -2,7 +2,7 @@ import { describe, it, before } from "node:test"; import hre from "hardhat"; import { ContractReturnType } from "@nomicfoundation/hardhat-viem/types"; -const { viem } = await hre.network.connect(); +const { viem } = await hre.network.create(); describe("Example EDR based test", () => { describe("revert", () => { diff --git a/packages/example-project/test/node/example-test.ts b/packages/example-project/test/node/example-test.ts index 58c38058e67..9ac8cb0a86f 100644 --- a/packages/example-project/test/node/example-test.ts +++ b/packages/example-project/test/node/example-test.ts @@ -4,7 +4,7 @@ import hre from "hardhat"; describe("Example EDR based test", () => { it("should work get the block number from the EDR Network", async () => { - const connection = await hre.network.connect(); + const connection = await hre.network.create(); const blockNumberAtStart = await connection.provider.request({ method: "eth_blockNumber", @@ -24,7 +24,7 @@ describe("Example EDR based test", () => { }); it("should show stack traces when a transaction reverts", async () => { - const connection = await hre.network.connect(); + const connection = await hre.network.create(); const Revert = await connection.ethers.getContractFactory("Revert"); const revert = await Revert.deploy(); diff --git a/packages/hardhat-errors/src/descriptors.ts b/packages/hardhat-errors/src/descriptors.ts index f011801c9b6..850d70fa16a 100644 --- a/packages/hardhat-errors/src/descriptors.ts +++ b/packages/hardhat-errors/src/descriptors.ts @@ -1067,7 +1067,7 @@ Try using another mnemonic or deriving less keys.`, messageTemplate: "The provider has been closed.", websiteTitle: "Provider closed", websiteDescription: - "The provider your are trying to use has been closed. Please create a new one using hre.network.connect() and try again.", + "The provider you are trying to use has been closed. Please create a new one using hre.network.create() and try again.", }, INCOMPATIBLE_EIP7702_FIELDS: { number: 723, @@ -2232,7 +2232,7 @@ Please ensure you're using one of the supported networks.`, To resolve this, make sure to add an account to the specified network in the Hardhat config. Alternatively, you can set a custom wallet client by passing it as a parameter in the relevant function: \`\`\`ts -const networkConnection = await hre.network.connect(...); +const networkConnection = await hre.network.create(...); const walletClient = await networkConnection.viem.getWalletClient(address); await networkConnection.viem.deployContract(contractName, constructorArgs, { walletClient }); diff --git a/packages/hardhat-ethers-chai-matchers/README.md b/packages/hardhat-ethers-chai-matchers/README.md index b30caf921e3..5fccbeb7de6 100644 --- a/packages/hardhat-ethers-chai-matchers/README.md +++ b/packages/hardhat-ethers-chai-matchers/README.md @@ -33,7 +33,7 @@ Here is an example of using the `emit` matcher: import { expect } from "chai"; import { network } from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await network.create(); it("some test", async function () { const contract = await ethers.deployContract("SomeContract"); diff --git a/packages/hardhat-ethers-chai-matchers/test/helpers/helpers.ts b/packages/hardhat-ethers-chai-matchers/test/helpers/helpers.ts index fe346454dde..eba83b0e1af 100644 --- a/packages/hardhat-ethers-chai-matchers/test/helpers/helpers.ts +++ b/packages/hardhat-ethers-chai-matchers/test/helpers/helpers.ts @@ -21,7 +21,7 @@ export async function initEnvironment(_artifactsPath: string): Promise<{ await hre.tasks.getTask("build").run({ force: false }); - const { ethers, provider } = await hre.network.connect(); + const { ethers, provider } = await hre.network.create(); return { provider, ethers }; } diff --git a/packages/hardhat-ethers-chai-matchers/test/index.ts b/packages/hardhat-ethers-chai-matchers/test/index.ts index 49b151290e9..a3c6309a0e6 100644 --- a/packages/hardhat-ethers-chai-matchers/test/index.ts +++ b/packages/hardhat-ethers-chai-matchers/test/index.ts @@ -15,7 +15,7 @@ describe("hardhat-ethers-chai-matchers plugin correctly initialized", () => { const hre = await createHardhatRuntimeEnvironment(hardhatConfig.default); - await hre.network.connect(); + await hre.network.create(); const result = await hre.tasks.getTask(["test", "mocha"]).run({ testFiles: ["./test/test.ts"], diff --git a/packages/hardhat-ethers-chai-matchers/test/multi-network-connections.ts b/packages/hardhat-ethers-chai-matchers/test/multi-network-connections.ts index 7be99c745b9..8e961a3ab9d 100644 --- a/packages/hardhat-ethers-chai-matchers/test/multi-network-connections.ts +++ b/packages/hardhat-ethers-chai-matchers/test/multi-network-connections.ts @@ -37,11 +37,11 @@ describe("handle multiple connections", () => { }, }); - ({ ethers } = await hre.network.connect({ + ({ ethers } = await hre.network.create({ network: "test1", })); - ({ ethers: ethers2 } = await hre.network.connect({ + ({ ethers: ethers2 } = await hre.network.create({ network: "test2", })); }); diff --git a/packages/hardhat-ethers/README.md b/packages/hardhat-ethers/README.md index c25fbedbfce..885824a1982 100644 --- a/packages/hardhat-ethers/README.md +++ b/packages/hardhat-ethers/README.md @@ -30,7 +30,7 @@ This plugin adds an `ethers` property to each network connection: ```ts import { network } from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await network.create(); const counter = await ethers.deployContract("Counter"); await counter.inc(); @@ -41,7 +41,7 @@ This object has the same API as [ethers.js](https://docs.ethers.org/), with some ### Provider -The plugin adds a `provider` property to the `ethers` object: an [ethers.js provider](https://docs.ethers.org/v6/single-page/#api_providers__Provider) connected to the network selected by `network.connect()`. +The plugin adds a `provider` property to the `ethers` object: an [ethers.js provider](https://docs.ethers.org/v6/single-page/#api_providers__Provider) connected to the network selected by `network.create()`. ```ts const blockNumber = await ethers.provider.getBlockNumber(); @@ -84,10 +84,10 @@ An [ethers.js provider](https://docs.ethers.org/v6/single-page/#api_providers__P ```ts // the network selected with --network option if specified, or the default network otherwise -const { ethers } = await network.connect(); +const { ethers } = await network.create(); // a specific network from the config -const { ethers } = await network.connect("mainnet"); +const { ethers } = await network.create("mainnet"); ``` ### `deployContract` diff --git a/packages/hardhat-ethers/test/helpers/helpers.ts b/packages/hardhat-ethers/test/helpers/helpers.ts index 9c573c3ce5c..6eb354a7760 100644 --- a/packages/hardhat-ethers/test/helpers/helpers.ts +++ b/packages/hardhat-ethers/test/helpers/helpers.ts @@ -30,7 +30,7 @@ export async function initializeTestEthers( const network = config.networks?.localhost !== undefined ? "localhost" : "default"; - const connection = await hre.network.connect(network); + const connection = await hre.network.create(network); const provider = connection.provider; const networkName = connection.networkName; diff --git a/packages/hardhat-ethers/test/index.ts b/packages/hardhat-ethers/test/index.ts index 86246953e5c..1ff442a0d7c 100644 --- a/packages/hardhat-ethers/test/index.ts +++ b/packages/hardhat-ethers/test/index.ts @@ -18,7 +18,7 @@ describe("hardhat-ethers plugin initialization", () => { plugins: [hardhatEthersPlugin], }); - ({ ethers } = await hre.network.connect()); + ({ ethers } = await hre.network.create()); }); it("should correctly set up ethers functionalities", async () => { diff --git a/packages/hardhat-ignition-ethers/README.md b/packages/hardhat-ignition-ethers/README.md index 5205705d883..50c4cb84c27 100644 --- a/packages/hardhat-ignition-ethers/README.md +++ b/packages/hardhat-ignition-ethers/README.md @@ -31,7 +31,7 @@ This plugin adds an `ignition` property to each network connection: import { network } from "hardhat"; import Counter from "../ignition/modules/Counter.js"; -const { ignition } = await network.connect(); +const { ignition } = await network.create(); const { counter } = await ignition.deploy(Counter); await counter.inc(); diff --git a/packages/hardhat-ignition-ethers/test/ignition-helper-exclusivity.ts b/packages/hardhat-ignition-ethers/test/ignition-helper-exclusivity.ts index 406e25b92ba..0eb7b11bcca 100644 --- a/packages/hardhat-ignition-ethers/test/ignition-helper-exclusivity.ts +++ b/packages/hardhat-ignition-ethers/test/ignition-helper-exclusivity.ts @@ -50,7 +50,7 @@ describe("ignition helper mutual exclusivity", () => { plugins: [fakeHardhatIgnitionViemPlugin, hardhatIgnitionEthersPlugin], }); - return hre.network.connect(); + return hre.network.create(); }, HardhatError.ERRORS.IGNITION.INTERNAL .ONLY_ONE_IGNITION_EXTENSION_PLUGIN_ALLOWED, diff --git a/packages/hardhat-ignition-ethers/test/test-helpers/create-hre.ts b/packages/hardhat-ignition-ethers/test/test-helpers/create-hre.ts index 960404a53cb..695cee630f9 100644 --- a/packages/hardhat-ignition-ethers/test/test-helpers/create-hre.ts +++ b/packages/hardhat-ignition-ethers/test/test-helpers/create-hre.ts @@ -10,7 +10,7 @@ import hardhatIgnitionEthers from "../../src/index.js"; export async function createConnection(): Promise { const hre = await createHre(); - const connection = await hre.network.connect(); + const connection = await hre.network.create(); await connection.provider.request({ method: "evm_setAutomine", diff --git a/packages/hardhat-ignition-viem/README.md b/packages/hardhat-ignition-viem/README.md index deb9762bf5e..ccccf31f265 100644 --- a/packages/hardhat-ignition-viem/README.md +++ b/packages/hardhat-ignition-viem/README.md @@ -31,7 +31,7 @@ This plugin adds an `ignition` property to each network connection: import { network } from "hardhat"; import Counter from "../ignition/modules/Counter.js"; -const { ignition } = await network.connect(); +const { ignition } = await network.create(); const { counter } = await ignition.deploy(Counter); await counter.write.inc(); diff --git a/packages/hardhat-ignition-viem/test/ignition-helper-exclusivity.ts b/packages/hardhat-ignition-viem/test/ignition-helper-exclusivity.ts index ae1a262866c..246759fa172 100644 --- a/packages/hardhat-ignition-viem/test/ignition-helper-exclusivity.ts +++ b/packages/hardhat-ignition-viem/test/ignition-helper-exclusivity.ts @@ -50,7 +50,7 @@ describe("ignition helper mutual exclusivity", () => { plugins: [fakeHardhatIgnitionEthersPlugin, hardhatIgnitionViemPlugin], }); - return hre.network.connect(); + return hre.network.create(); }, HardhatError.ERRORS.IGNITION.INTERNAL .ONLY_ONE_IGNITION_EXTENSION_PLUGIN_ALLOWED, diff --git a/packages/hardhat-ignition-viem/test/test-helpers/create-hre.ts b/packages/hardhat-ignition-viem/test/test-helpers/create-hre.ts index 72ab4169449..b7e1b3ab234 100644 --- a/packages/hardhat-ignition-viem/test/test-helpers/create-hre.ts +++ b/packages/hardhat-ignition-viem/test/test-helpers/create-hre.ts @@ -10,7 +10,7 @@ import hardhatIgnitionViem from "../../src/index.js"; export async function createConnection(): Promise { const hre = await createHre(); - const connection = await hre.network.connect(); + const connection = await hre.network.create(); await connection.provider.request({ method: "evm_setAutomine", diff --git a/packages/hardhat-ignition/src/internal/tasks/deploy.ts b/packages/hardhat-ignition/src/internal/tasks/deploy.ts index fb4a4349189..21f6b168004 100644 --- a/packages/hardhat-ignition/src/internal/tasks/deploy.ts +++ b/packages/hardhat-ignition/src/internal/tasks/deploy.ts @@ -54,7 +54,7 @@ const taskDeploy: NewTaskActionFunction = async ( }, hre: HardhatRuntimeEnvironment, ): Promise => { - const connection = await hre.network.connect(); + const connection = await hre.network.create(); const chainId = Number( await connection.provider.request({ diff --git a/packages/hardhat-ignition/src/internal/tasks/track-tx.ts b/packages/hardhat-ignition/src/internal/tasks/track-tx.ts index 6f53649acc1..d4c2eeca602 100644 --- a/packages/hardhat-ignition/src/internal/tasks/track-tx.ts +++ b/packages/hardhat-ignition/src/internal/tasks/track-tx.ts @@ -24,7 +24,7 @@ const taskTransactions: NewTaskActionFunction = async ( await verifyArtifactsVersion(deploymentDir); - const connection = await hre.network.connect(); + const connection = await hre.network.create(); const output = await trackTransaction( deploymentDir, diff --git a/packages/hardhat-ignition/src/internal/tasks/transactions.ts b/packages/hardhat-ignition/src/internal/tasks/transactions.ts index b252af0be42..eb60ab8a211 100644 --- a/packages/hardhat-ignition/src/internal/tasks/transactions.ts +++ b/packages/hardhat-ignition/src/internal/tasks/transactions.ts @@ -32,7 +32,7 @@ const taskTransactions: NewTaskActionFunction< ); // TODO: HH3 revisit looking up the network name for display - const networkName = (await hre.network.connect()).networkName; + const networkName = (await hre.network.create()).networkName; console.log( await calculateListTransactionsDisplay( diff --git a/packages/hardhat-ignition/src/internal/tasks/verify.ts b/packages/hardhat-ignition/src/internal/tasks/verify.ts index 2a5b5632a37..b27c4e7a59c 100644 --- a/packages/hardhat-ignition/src/internal/tasks/verify.ts +++ b/packages/hardhat-ignition/src/internal/tasks/verify.ts @@ -56,7 +56,7 @@ export async function verify( deploymentId, ); - const connection = await hre.network.connect(); + const connection = await hre.network.create(); for await (const contractInfo of getVerificationInformationFn( deploymentDir, diff --git a/packages/hardhat-ignition/test/test-helpers/create-hre.ts b/packages/hardhat-ignition/test/test-helpers/create-hre.ts index b6c1885c6cc..ef0a70acca2 100644 --- a/packages/hardhat-ignition/test/test-helpers/create-hre.ts +++ b/packages/hardhat-ignition/test/test-helpers/create-hre.ts @@ -10,7 +10,7 @@ import hardhatIgnitionPlugin from "../../src/index.js"; export async function createConnection(): Promise { const hre = await createHre(); - const connection = await hre.network.connect(); + const connection = await hre.network.create(); await connection.provider.request({ method: "evm_setAutomine", diff --git a/packages/hardhat-ignition/test/test-helpers/use-ignition-project.ts b/packages/hardhat-ignition/test/test-helpers/use-ignition-project.ts index e3cb594f8c1..9f8b1c88d7e 100644 --- a/packages/hardhat-ignition/test/test-helpers/use-ignition-project.ts +++ b/packages/hardhat-ignition/test/test-helpers/use-ignition-project.ts @@ -110,7 +110,7 @@ export function useEphemeralIgnitionProject(fixtureProjectName: string): void { projectPath, ); - const connection = await hre.network.connect(); + const connection = await hre.network.create(); await connection.provider.request({ method: "evm_setAutomine", @@ -173,7 +173,7 @@ export function useFileIgnitionProject( deploymentId, ); - const connection = await hre.network.connect(); + const connection = await hre.network.create(); await connection.provider.request({ method: "evm_setAutomine", diff --git a/packages/hardhat-ledger/README.md b/packages/hardhat-ledger/README.md index 74ce830bd5a..92441f43e4f 100644 --- a/packages/hardhat-ledger/README.md +++ b/packages/hardhat-ledger/README.md @@ -82,7 +82,7 @@ Usage Example with Viem: import hre from "hardhat"; import { stringToHex } from "viem"; -const { viem } = await hre.network.connect("yourNetworkName"); +const { viem } = await hre.network.create("yourNetworkName"); const ledgerAddress = "0x..."; // Your ledger address @@ -101,7 +101,7 @@ Usage Example with the provider: ```typescript import hre from "hardhat"; -const { provider, ethers } = await hre.network.connect("yourNetworkName"); +const { provider, ethers } = await hre.network.create("yourNetworkName"); const ledgerAddress = "0x..."; // Your ledger address diff --git a/packages/hardhat-ledger/test/integration.ts b/packages/hardhat-ledger/test/integration.ts index e2c9997441f..8d579dffc44 100644 --- a/packages/hardhat-ledger/test/integration.ts +++ b/packages/hardhat-ledger/test/integration.ts @@ -53,7 +53,7 @@ describe("LedgerHandler", () => { }, }); - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const res = await provider.request({ method: "eth_accounts" }); @@ -76,7 +76,7 @@ describe("LedgerHandler", () => { }, }); - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const res = await provider.request({ method: "eth_accounts" }); @@ -94,7 +94,7 @@ describe("LedgerHandler", () => { }, }); - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const res = await provider.request({ method: "eth_accounts" }); @@ -119,12 +119,12 @@ describe("LedgerHandler", () => { }, }); - const { provider: firsProvider } = - await hre.network.connect("firstConnection"); + const { provider: firstProvider } = + await hre.network.create("firstConnection"); const { provider: secondProvider } = - await hre.network.connect("secondConnection"); + await hre.network.create("secondConnection"); - const firstRes = await firsProvider.request({ method: "eth_accounts" }); + const firstRes = await firstProvider.request({ method: "eth_accounts" }); assert.deepEqual(firstRes, [ ...HARDHAT_ACCOUNTS_ADDRESSES, ...LEDGER_ADDRESSES, diff --git a/packages/hardhat-network-helpers/README.md b/packages/hardhat-network-helpers/README.md index b598d7a5eb0..2755786ecbf 100644 --- a/packages/hardhat-network-helpers/README.md +++ b/packages/hardhat-network-helpers/README.md @@ -30,7 +30,7 @@ This plugin adds a `networkHelpers` property to each network connection: ```ts import { network } from "hardhat"; -const { networkHelpers } = await network.connect(); +const { networkHelpers } = await network.create(); // immediately mine a new block await networkHelpers.mine(); @@ -64,11 +64,11 @@ Example: ```ts // Mine 1 block (default behavior) -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.mine(); // Mine 10 blocks with an interval of 60 seconds between each block -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.mine(10, { interval: 60 }); ``` @@ -91,7 +91,7 @@ Returns: A promise that resolves once the required blocks have been mined. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.mineUpTo(150); // Mines until block with block number 150 ``` @@ -118,7 +118,7 @@ Returns: A promise that resolves to a string containing the hexadecimal code ret Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); const storageData = await networkHelpers.getStorageAt("0x123...", 0); ``` @@ -141,7 +141,7 @@ Returns: A promise that resolves once the account is impersonated. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.impersonateAccount("0x123..."); ``` @@ -165,7 +165,7 @@ Returns: A promise that resolves once the balance has been set. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.setBalance("0x123...", 1000000000000000000n); // Sets 1 ETH ``` @@ -189,7 +189,7 @@ Returns: A promise that resolves once the code is set. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.setCode("0x123...", "0x6001600101..."); ``` @@ -213,7 +213,7 @@ Returns: A promise that resolves once the nonce is set. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.setNonce("0x123...", 10); // Set the nonce of the account to 10 ``` @@ -238,7 +238,7 @@ Returns: A promise that resolves once the storage value is set. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.setStorageAt("0x123...", 0, 0x0000...); ``` @@ -261,7 +261,7 @@ Returns: A promise that resolves once the impersonation is stopped. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.stopImpersonatingAccount("0x123..."); ``` @@ -282,7 +282,7 @@ Returns: A promise that resolves to a `SnapshotRestorer` object, which contains Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); const snapshot = await networkHelpers.takeSnapshot(); await snapshot.restore(); // Restores the blockchain state ``` @@ -365,7 +365,7 @@ Returns: `true` if successful, otherwise `false`. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); const success = await networkHelpers.dropTransaction("0x123..."); ``` @@ -388,7 +388,7 @@ Returns: A promise that resolves once the gas limit has been set. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.setBlockGasLimit(1000000); // Set block gas limit to 1,000,000 ``` @@ -411,7 +411,7 @@ Returns: A promise that resolves once the coinbase address has been set. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.setCoinbase("0x123..."); ``` @@ -434,7 +434,7 @@ Returns: A promise that resolves once the base fee is set. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.setNextBlockBaseFeePerGas(1000000); // Set base fee to 1,000,000 ``` @@ -457,7 +457,7 @@ Returns: A promise that resolves once the PREVRANDAO value is set. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.setPrevRandao(123456789); // Set the PREVRANDAO value ``` @@ -482,7 +482,7 @@ Returns: A promise that resolves to the timestamp of the mined block. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); await networkHelpers.time.increase(12); ``` @@ -505,7 +505,7 @@ Returns: A promise that resolves when the block is successfully mined. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); networkHelpers.time.increaseTo(1700000000); ``` @@ -524,7 +524,7 @@ Returns: The timestamp of the latest block. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); const timestamp = await networkHelpers.time.latest(); ``` @@ -543,7 +543,7 @@ Returns: A promise that resolves to the latest block number. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); const blockNumber = await networkHelpers.time.latestBlock(); ``` @@ -564,7 +564,7 @@ Parameters: Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); networkHelpers.time.setNextBlockTimestamp(1700000000); ``` @@ -589,7 +589,7 @@ Returns: The equivalent duration in seconds. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); const seconds = networkHelpers.time.duration.years(1); ``` @@ -612,7 +612,7 @@ Returns: The equivalent duration in seconds. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); const seconds = networkHelpers.time.duration.weeks(1); ``` @@ -635,7 +635,7 @@ Returns: The equivalent duration in seconds. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); const seconds = networkHelpers.time.duration.days(1); ``` @@ -658,7 +658,7 @@ Returns: The equivalent duration in seconds. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); const seconds = networkHelpers.time.duration.hours(1); ``` @@ -681,7 +681,7 @@ Returns: The equivalent duration in seconds. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); const seconds = networkHelpers.time.duration.minutes(1); ``` @@ -704,7 +704,7 @@ Returns: The same number of seconds. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); const seconds = networkHelpers.time.duration.seconds(1); ``` @@ -727,6 +727,6 @@ Returns: The equivalent duration in seconds. Example: ```ts -const { networkHelpers } = await hre.network.connect(); +const { networkHelpers } = await hre.network.create(); const seconds = networkHelpers.time.duration.millis(1500); // Returns 1 ``` diff --git a/packages/hardhat-network-helpers/src/types.ts b/packages/hardhat-network-helpers/src/types.ts index ac04c2c7f71..dd28a2f6d53 100644 --- a/packages/hardhat-network-helpers/src/types.ts +++ b/packages/hardhat-network-helpers/src/types.ts @@ -25,7 +25,7 @@ export interface NetworkHelpers< * @returns `true` if successful, otherwise `false`. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * const success = await networkHelpers.dropTransaction('0x123...'); */ dropTransaction(txHash: string): Promise; @@ -39,7 +39,7 @@ export interface NetworkHelpers< * @returns A promise that resolves to a string containing the hexadecimal code retrieved. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * const storageData = await networkHelpers.getStorageAt("0x123...", 0); */ getStorageAt( @@ -55,7 +55,7 @@ export interface NetworkHelpers< * @returns A promise that resolves once the account is impersonated. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.impersonateAccount("0x123..."); */ impersonateAccount(address: string): Promise; @@ -93,12 +93,12 @@ export interface NetworkHelpers< * * @example * // Mine 1 block (default behavior) - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.mine(); * * @example * // Mine 10 blocks with an interval of 60 seconds between each block - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.mine(10, { interval: 60 }); */ mine(blocks?: NumberLike, options?: { interval?: NumberLike }): Promise; @@ -110,7 +110,7 @@ export interface NetworkHelpers< * @returns A promise that resolves once the required blocks have been mined. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.mineUpTo(150); // Mines until block with block number 150 */ mineUpTo(blockNumber: NumberLike): Promise; @@ -123,7 +123,7 @@ export interface NetworkHelpers< * @returns A promise that resolves once the balance has been set. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.setBalance("0x123...", 1000000000000000000n); // Sets 1 ETH */ setBalance(address: string, balance: NumberLike): Promise; @@ -135,7 +135,7 @@ export interface NetworkHelpers< * @returns A promise that resolves once the gas limit has been set. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.setBlockGasLimit(1000000); // Set block gas limit to 1,000,000 */ setBlockGasLimit(blockGasLimit: NumberLike): Promise; @@ -148,7 +148,7 @@ export interface NetworkHelpers< * @returns A promise that resolves once the code is set. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.setCode("0x123...", "0x6001600101..."); */ setCode(address: string, code: string): Promise; @@ -160,7 +160,7 @@ export interface NetworkHelpers< * @returns A promise that resolves once the coinbase address has been set. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.setCoinbase("0x123..."); */ setCoinbase(address: string): Promise; @@ -172,7 +172,7 @@ export interface NetworkHelpers< * @returns A promise that resolves once the base fee is set. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.setNextBlockBaseFeePerGas(1000000); // Set base fee to 1,000,000 */ setNextBlockBaseFeePerGas(baseFeePerGas: NumberLike): Promise; @@ -185,7 +185,7 @@ export interface NetworkHelpers< * @returns A promise that resolves once the nonce is set. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.setNonce("0x123...", 10); // Set the nonce of the account to 10 */ setNonce(address: string, nonce: NumberLike): Promise; @@ -197,7 +197,7 @@ export interface NetworkHelpers< * @returns A promise that resolves once the PREVRANDAO value is set. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.setPrevRandao(123456789); // Set the PREVRANDAO value */ setPrevRandao(prevRandao: NumberLike): Promise; @@ -211,7 +211,7 @@ export interface NetworkHelpers< * @returns A promise that resolves once the storage value is set. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.setStorageAt("0x123...", 0, 0x0000...); */ setStorageAt( @@ -227,7 +227,7 @@ export interface NetworkHelpers< * @returns A promise that resolves once the impersonation is stopped. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.stopImpersonatingAccount("0x123..."); */ stopImpersonatingAccount(address: string): Promise; @@ -237,7 +237,7 @@ export interface NetworkHelpers< * @returns A promise that resolves to a `SnapshotRestorer` object, which contains a `restore` method to reset the network to this snapshot. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * const snapshot = await networkHelpers.takeSnapshot(); * await snapshot.restore(); // Restores the blockchain state */ @@ -254,7 +254,7 @@ export interface Time { * @return The timestamp of the mined block. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * await networkHelpers.time.increase(12); */ increase(amountInSeconds: NumberLike): Promise; @@ -266,7 +266,7 @@ export interface Time { * @return A promise that resolves when the block is successfully mined. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * networkHelpers.time.increaseTo(1700000000); */ increaseTo(timestamp: NumberLike | Date): Promise; @@ -277,7 +277,7 @@ export interface Time { * @return The timestamp of the latest block. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * const timestamp = await networkHelpers.time.latest(); */ latest(): Promise; @@ -288,7 +288,7 @@ export interface Time { * @returns A promise that resolves to the latest block number. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * const blockNumber = await networkHelpers.time.latestBlock(); */ latestBlock(): Promise; @@ -299,7 +299,7 @@ export interface Time { * @param timestamp Can be `Date` or Epoch seconds. Must be greater than the latest block's timestamp. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * networkHelpers.time.setNextBlockTimestamp(1700000000); */ setNextBlockTimestamp(timestamp: NumberLike | Date): Promise; @@ -312,7 +312,7 @@ export interface Duration { * @returns The equivalent duration in seconds. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * const seconds = networkHelpers.time.duration.years(1); */ years(n: number): number; @@ -324,7 +324,7 @@ export interface Duration { * @returns The equivalent duration in seconds. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * const seconds = networkHelpers.time.duration.weeks(1); */ weeks(n: number): number; @@ -336,7 +336,7 @@ export interface Duration { * @returns The equivalent duration in seconds. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * const seconds = networkHelpers.time.duration.days(1); */ days(n: number): number; @@ -348,7 +348,7 @@ export interface Duration { * @returns The equivalent duration in seconds. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * const seconds = networkHelpers.time.duration.hours(1); */ hours(n: number): number; @@ -360,7 +360,7 @@ export interface Duration { * @returns The equivalent duration in seconds. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * const seconds = networkHelpers.time.duration.minutes(1); */ minutes(n: number): number; @@ -372,7 +372,7 @@ export interface Duration { * @returns The same number of seconds. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * const seconds = networkHelpers.time.duration.seconds(1); */ seconds(n: number): number; @@ -384,7 +384,7 @@ export interface Duration { * @returns The equivalent duration in seconds. * * @example - * const { networkHelpers } = await hre.network.connect(); + * const { networkHelpers } = await hre.network.create(); * const seconds = networkHelpers.time.duration.millis(1500); // Returns 1 */ millis(n: number): number; diff --git a/packages/hardhat-network-helpers/test/helpers/helpers.ts b/packages/hardhat-network-helpers/test/helpers/helpers.ts index 9e0d68a3650..d6f10fd5761 100644 --- a/packages/hardhat-network-helpers/test/helpers/helpers.ts +++ b/packages/hardhat-network-helpers/test/helpers/helpers.ts @@ -18,7 +18,7 @@ export async function initializeNetwork< const hre = await createHardhatRuntimeEnvironment({ networks: { default: { type: "edr-simulated", ...config } }, }); - const connection = await hre.network.connect(); + const connection = await hre.network.create(); const provider = connection.provider; diff --git a/packages/hardhat-network-helpers/test/index.ts b/packages/hardhat-network-helpers/test/index.ts index abbcda6092c..700956ca4c5 100644 --- a/packages/hardhat-network-helpers/test/index.ts +++ b/packages/hardhat-network-helpers/test/index.ts @@ -21,7 +21,7 @@ describe("hardhat-network-helpers plugin initialization", () => { plugins: [hardhatNetworkHelpersPlugin], }); - ({ networkHelpers } = await hre.network.connect()); + ({ networkHelpers } = await hre.network.create()); }); it("should correctly set up the network-helpers class", async () => { @@ -73,7 +73,7 @@ describe("hardhat-network-helpers plugin initialization", () => { ], }); - ({ networkHelpers } = await hre.network.connect({ + ({ networkHelpers } = await hre.network.create({ network: "non-test", })); }); diff --git a/packages/hardhat-toolbox-mocha-ethers/test/fixture-projects/toolbox/scripts/script.ts b/packages/hardhat-toolbox-mocha-ethers/test/fixture-projects/toolbox/scripts/script.ts index ba3599680b4..355c5825634 100644 --- a/packages/hardhat-toolbox-mocha-ethers/test/fixture-projects/toolbox/scripts/script.ts +++ b/packages/hardhat-toolbox-mocha-ethers/test/fixture-projects/toolbox/scripts/script.ts @@ -1,7 +1,7 @@ import { expect } from "chai"; import { network } from "hardhat"; -const { ethers, networkHelpers } = await network.connect(); +const { ethers, networkHelpers } = await network.create(); // chai matchers should be available expect("0x0000010AB").to.not.hexEqual("0x0010abc"); diff --git a/packages/hardhat-toolbox-viem/test/fixture-projects/toolbox/scripts/script.ts b/packages/hardhat-toolbox-viem/test/fixture-projects/toolbox/scripts/script.ts index 367582e0d64..ca42507374e 100644 --- a/packages/hardhat-toolbox-viem/test/fixture-projects/toolbox/scripts/script.ts +++ b/packages/hardhat-toolbox-viem/test/fixture-projects/toolbox/scripts/script.ts @@ -1,6 +1,6 @@ import { network } from "hardhat"; -const { networkHelpers, viem } = await network.connect(); +const { networkHelpers, viem } = await network.create(); // network helpers should be available await networkHelpers.mine(); diff --git a/packages/hardhat-verify/README.md b/packages/hardhat-verify/README.md index b96137d3a55..a46c5571183 100644 --- a/packages/hardhat-verify/README.md +++ b/packages/hardhat-verify/README.md @@ -87,7 +87,7 @@ await verifyContract( ## Advanced Usage for Plugin Authors -If you're building a Hardhat plugin that needs direct access to the Etherscan API (for example, to verify proxy contracts or make custom API calls), you can access the Etherscan instance through `network.connect()`. +If you're building a Hardhat plugin that needs direct access to the Etherscan API (for example, to verify proxy contracts or make custom API calls), you can access the Etherscan instance through `network.create()`. ### Accessing the Etherscan Instance @@ -95,7 +95,7 @@ If you're building a Hardhat plugin that needs direct access to the Etherscan AP import type { HardhatRuntimeEnvironment } from "hardhat/types"; export async function myCustomVerificationTask(hre: HardhatRuntimeEnvironment) { - const { verification } = await hre.network.connect(); + const { verification } = await hre.network.create(); // Access Etherscan instance const etherscan = verification.etherscan; @@ -131,7 +131,7 @@ export async function myCustomVerificationTask(hre: HardhatRuntimeEnvironment) { For API endpoints not covered by the standard methods, use `customApiCall()`: ```typescript -const { verification } = await hre.network.connect(); +const { verification } = await hre.network.create(); // Make a custom API call (apikey and chainid are added automatically) const response = await verification.etherscan.customApiCall({ diff --git a/packages/hardhat-verify/src/internal/etherscan.types.ts b/packages/hardhat-verify/src/internal/etherscan.types.ts index 7bee78402de..6c9ba71b503 100644 --- a/packages/hardhat-verify/src/internal/etherscan.types.ts +++ b/packages/hardhat-verify/src/internal/etherscan.types.ts @@ -81,12 +81,12 @@ export type EtherscanCustomApiCallOptions = * * This interface is designed for plugin authors who need direct access * to Etherscan's verification API beyond the standard verification - * workflow. It can be accessed through `network.connect()` in the + * workflow. It can be accessed through `network.create()` in the * Hardhat Runtime Environment. * * @example * ```typescript - * const { verification } = await hre.network.connect(); + * const { verification } = await hre.network.create(); * const etherscan = verification.etherscan; * * // Use Etherscan methods diff --git a/packages/hardhat-verify/src/internal/verification.ts b/packages/hardhat-verify/src/internal/verification.ts index a7d70555d75..64a0f176d43 100644 --- a/packages/hardhat-verify/src/internal/verification.ts +++ b/packages/hardhat-verify/src/internal/verification.ts @@ -110,7 +110,7 @@ export async function verifyContract( ); } - const connection = await network.connect(); + const connection = await network.create(); const { networkName } = connection; const resolvedProvider = provider ?? connection.provider; diff --git a/packages/hardhat-verify/test/hook-handlers/network.ts b/packages/hardhat-verify/test/hook-handlers/network.ts index f5c9b36a565..b4fae9c068f 100644 --- a/packages/hardhat-verify/test/hook-handlers/network.ts +++ b/packages/hardhat-verify/test/hook-handlers/network.ts @@ -19,7 +19,7 @@ describe("hook-handlers/network", () => { const hre = await createHardhatRuntimeEnvironment({ plugins: [hardhatVerify], }); - connection = await hre.network.connect(); + connection = await hre.network.create(); }); it("should extend connection with verification property", () => { @@ -100,8 +100,8 @@ describe("hook-handlers/network", () => { const hre = await createHardhatRuntimeEnvironment({ plugins: [hardhatVerify], }); - const connection1 = await hre.network.connect(); - const connection2 = await hre.network.connect(); + const connection1 = await hre.network.create(); + const connection2 = await hre.network.create(); assert.notEqual( connection1.verification, diff --git a/packages/hardhat-verify/test/verification.ts b/packages/hardhat-verify/test/verification.ts index 58f71aead2f..5445ba60431 100644 --- a/packages/hardhat-verify/test/verification.ts +++ b/packages/hardhat-verify/test/verification.ts @@ -46,7 +46,7 @@ describe("verification", () => { }); it("should verify a contract with no constructor arguments or libraries", async () => { - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const address = await deployContract("Counter", [], {}, hre, provider); const result = await verifyContract( @@ -64,7 +64,7 @@ describe("verification", () => { it("should verify a contract with constructor arguments", async () => { const constructorArgs = [0, true]; - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const address = await deployContract( "CounterWithArgs", [0, true], @@ -88,7 +88,7 @@ describe("verification", () => { }); it("should verify a contract with libraries", async () => { - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const libAddress = await deployContract( "CounterLib", [], @@ -121,7 +121,7 @@ describe("verification", () => { it("should verify a contract with constructor arguments and libraries", async () => { const constructorArgs = [0, true]; - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const libAddress = await deployContract( "CounterLib", [], @@ -163,7 +163,7 @@ describe("verification", () => { }, }, }); - const { provider } = await localHre.network.connect(); + const { provider } = await localHre.network.create(); const address = await deployContract( "Counter", [], diff --git a/packages/hardhat-viem-assertions/README.md b/packages/hardhat-viem-assertions/README.md index 470db114989..9057b12d234 100644 --- a/packages/hardhat-viem-assertions/README.md +++ b/packages/hardhat-viem-assertions/README.md @@ -30,7 +30,7 @@ You don't need to do anything else to use this plugin. The `viem` object added b Here is an example of using the `balancesHaveChanged` assertion: ```ts -const { viem } = await hre.network.connect(); +const { viem } = await hre.network.create(); const [bobWalletClient, aliceWalletClient] = await viem.getWalletClients(); diff --git a/packages/hardhat-viem-assertions/test/internal/assertions/balances-have-changed.ts b/packages/hardhat-viem-assertions/test/internal/assertions/balances-have-changed.ts index b833e79b07f..2bf8379034d 100644 --- a/packages/hardhat-viem-assertions/test/internal/assertions/balances-have-changed.ts +++ b/packages/hardhat-viem-assertions/test/internal/assertions/balances-have-changed.ts @@ -17,7 +17,7 @@ describe("balancesHaveChanged", () => { plugins: [hardhatViem, hardhatViemAssertions], }); - ({ viem } = await hre.network.connect()); + ({ viem } = await hre.network.create()); }); it("should check that a single balances has changed", async () => { diff --git a/packages/hardhat-viem-assertions/test/internal/assertions/emit/emit-with-args.ts b/packages/hardhat-viem-assertions/test/internal/assertions/emit/emit-with-args.ts index 00b9aa28033..210b696ecc6 100644 --- a/packages/hardhat-viem-assertions/test/internal/assertions/emit/emit-with-args.ts +++ b/packages/hardhat-viem-assertions/test/internal/assertions/emit/emit-with-args.ts @@ -32,7 +32,7 @@ describe("emitWithArgs", () => { }); beforeEach(async () => { - ({ provider, viem } = await hre.network.connect()); + ({ provider, viem } = await hre.network.create()); }); it("should check that the event was emitted with the correct single argument", async () => { diff --git a/packages/hardhat-viem-assertions/test/internal/assertions/emit/emit.ts b/packages/hardhat-viem-assertions/test/internal/assertions/emit/emit.ts index d6fa6b448f2..2a982dd4a3c 100644 --- a/packages/hardhat-viem-assertions/test/internal/assertions/emit/emit.ts +++ b/packages/hardhat-viem-assertions/test/internal/assertions/emit/emit.ts @@ -29,7 +29,7 @@ describe("emit", () => { }); beforeEach(async () => { - ({ viem } = await hre.network.connect()); + ({ viem } = await hre.network.create()); }); it("should check that the event was emitted", async () => { diff --git a/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert-with-custom-error-with-args.ts b/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert-with-custom-error-with-args.ts index 3266794d196..559e6b653ce 100644 --- a/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert-with-custom-error-with-args.ts +++ b/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert-with-custom-error-with-args.ts @@ -29,7 +29,7 @@ describe("revertWithCustomErrorWithArgs", () => { }); beforeEach(async () => { - ({ viem } = await hre.network.connect()); + ({ viem } = await hre.network.create()); }); it("should check that the function reverts with uint", async () => { diff --git a/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert-with-custom-error.ts b/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert-with-custom-error.ts index 1ae25ce682a..592a97cb01a 100644 --- a/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert-with-custom-error.ts +++ b/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert-with-custom-error.ts @@ -29,7 +29,7 @@ describe("revertWithCustomError", () => { }); beforeEach(async () => { - ({ viem } = await hre.network.connect()); + ({ viem } = await hre.network.create()); }); it("should check that the function reverts", async () => { diff --git a/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert-with.ts b/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert-with.ts index 12c5c1a7392..bcafdc66864 100644 --- a/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert-with.ts +++ b/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert-with.ts @@ -29,7 +29,7 @@ describe("revertWith", () => { }); beforeEach(async () => { - ({ viem } = await hre.network.connect()); + ({ viem } = await hre.network.create()); }); it("should check that the function reverts", async () => { diff --git a/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert.ts b/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert.ts index b637626f4dc..24b802e9987 100644 --- a/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert.ts +++ b/packages/hardhat-viem-assertions/test/internal/assertions/revert/revert.ts @@ -28,7 +28,7 @@ describe("revert", () => { }); beforeEach(async () => { - ({ viem } = await hre.network.connect()); + ({ viem } = await hre.network.create()); }); it("should check that the function reverts", async () => { diff --git a/packages/hardhat-viem/README.md b/packages/hardhat-viem/README.md index b33c13abb33..fe80e3f0ea9 100644 --- a/packages/hardhat-viem/README.md +++ b/packages/hardhat-viem/README.md @@ -30,7 +30,7 @@ This plugin adds a `viem` property to each Network Connection: ```ts import { network } from "hardhat"; -const { viem } = await hre.network.connect(); +const { viem } = await network.create(); const publicClient = await viem.getPublicClient(); console.log(await publicClient.getBlockNumber()); diff --git a/packages/hardhat-viem/test/clients.ts b/packages/hardhat-viem/test/clients.ts index 67285f791c2..62dac7469e1 100644 --- a/packages/hardhat-viem/test/clients.ts +++ b/packages/hardhat-viem/test/clients.ts @@ -556,7 +556,7 @@ describe("clients", () => { }); it("should be able to query the blockchain using the public client", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const publicClient = await networkConnection.viem.getPublicClient(); const blockNumber = await publicClient.getBlockNumber(); @@ -565,7 +565,7 @@ describe("clients", () => { }); it("should be able to query the blockchain using the wallet client", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const publicClient = await networkConnection.viem.getPublicClient(); const [fromWalletClient, toWalletClient] = @@ -605,7 +605,7 @@ describe("clients", () => { }); it("should be able to query the blockchain using the test client", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const publicClient = await networkConnection.viem.getPublicClient(); const testClient = await networkConnection.viem.getTestClient(); @@ -627,7 +627,7 @@ describe("clients", () => { }, }); - const { viem } = await hre.network.connect({ + const { viem } = await hre.network.create({ network: "edrOptimism", chainType: "op", }); diff --git a/packages/hardhat-viem/test/contracts.ts b/packages/hardhat-viem/test/contracts.ts index 2fc98ee5dc3..1f9c89011a8 100644 --- a/packages/hardhat-viem/test/contracts.ts +++ b/packages/hardhat-viem/test/contracts.ts @@ -33,7 +33,7 @@ describe("contracts", () => { describe("deployContract", () => { it("should be able to deploy a contract without constructor args", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const contract = await networkConnection.viem.deployContract( "WithoutConstructorArgs", ); @@ -44,7 +44,7 @@ describe("contracts", () => { }); it("should be able to deploy a contract with constructor args", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const [defaultWalletClient] = await networkConnection.viem.getWalletClients(); const contract = await networkConnection.viem.deployContract( @@ -64,7 +64,7 @@ describe("contracts", () => { }); it("should be able to deploy a contract with a different wallet client", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const [_, secondWalletClient] = await networkConnection.viem.getWalletClients(); const contract = await networkConnection.viem.deployContract( @@ -78,7 +78,7 @@ describe("contracts", () => { }); it("should be able to deploy a contract with initial ETH", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const publicClient = await networkConnection.viem.getPublicClient(); const [defaultWalletClient] = await networkConnection.viem.getWalletClients(); @@ -113,7 +113,7 @@ describe("contracts", () => { }); it("should be able to deploy a contract with normal library linked", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const normalLibContract = await networkConnection.viem.deployContract("NormalLib"); @@ -132,7 +132,7 @@ describe("contracts", () => { }); it("should be able to deploy a contract with constructor library linked", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const ctorLibContract = await networkConnection.viem.deployContract( "contracts/WithLibs.sol:ConstructorLib", ); @@ -152,7 +152,7 @@ describe("contracts", () => { }); it("should be able to deploy a contract with both normal and constructor libraries linked", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const [ctorLibContract, normalLibContract] = await Promise.all([ networkConnection.viem.deployContract( "contracts/WithLibs.sol:ConstructorLib", @@ -197,7 +197,7 @@ describe("contracts", () => { }, }); - const networkConnection = await hre.network.connect({ + const networkConnection = await hre.network.create({ network: "edrOptimism", chainType: "op", }); @@ -211,7 +211,7 @@ describe("contracts", () => { }); it("should throw an error if the contract address can't be retrieved", async (t) => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const publicClient = await networkConnection.viem.getPublicClient(); const [walletClient] = await networkConnection.viem.getWalletClients(); @@ -275,7 +275,7 @@ describe("contracts", () => { hre.hooks.registerHandlers("network", networkHooks); - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); await assertRejectsWithHardhatError( networkConnection.viem.deployContract("WithoutConstructorArgs"), @@ -298,7 +298,7 @@ describe("contracts", () => { // for tests. // TODO: analyze why this test is failing in the ci it.skip("should wait for confirmations", { timeout: 500 }, async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const publicClient = await networkConnection.viem.getPublicClient(); const testClient = await networkConnection.viem.getTestClient(); // We wait for twice the polling interval to ensure the client has @@ -345,7 +345,7 @@ describe("contracts", () => { }); it("should throw if the confirmations parameter is less than 0", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); await assertRejectsWithHardhatError( networkConnection.viem.deployContract("WithoutConstructorArgs", [], { @@ -359,7 +359,7 @@ describe("contracts", () => { }); it("should throw if the confirmations parameter is 0", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); await assertRejectsWithHardhatError( networkConnection.viem.deployContract("WithoutConstructorArgs", [], { @@ -374,7 +374,7 @@ describe("contracts", () => { }); it("should throw if there are any missing libraries", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); await assertRejectsWithHardhatError( networkConnection.viem.deployContract("OnlyNormalLib"), @@ -391,7 +391,7 @@ describe("contracts", () => { }); it("should throw if there are libraries that are not needed", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const constructorLibContract = await networkConnection.viem.deployContract( "contracts/WithLibs.sol:ConstructorLib", @@ -437,7 +437,7 @@ describe("contracts", () => { }); it("should throw if the provided library names are ambiguous", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const constructorLibConstructorLibContract = await networkConnection.viem.deployContract( "contracts/ConstructorLib.sol:ConstructorLib", @@ -511,7 +511,7 @@ describe("contracts", () => { }); it("should throw if the provided library names are overlapping", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const constructorLibContract = await networkConnection.viem.deployContract( "contracts/WithLibs.sol:ConstructorLib", @@ -540,7 +540,7 @@ describe("contracts", () => { }); it("should throw if the provided library addresses are invalid", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); await assertRejectsWithHardhatError( networkConnection.viem.deployContract("OnlyNormalLib", [], { @@ -563,7 +563,7 @@ describe("contracts", () => { describe("sendDeploymentTransaction", () => { it("should return the contract and the deployment transaction", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const publicClient = await networkConnection.viem.getPublicClient(); const { contract, deploymentTransaction } = await networkConnection.viem.sendDeploymentTransaction( @@ -592,7 +592,7 @@ describe("contracts", () => { }); it("should return the contract with linked libraries and the deployment transaction", async () => { - const networkConnection = await hre.network.connect(); + const networkConnection = await hre.network.create(); const publicClient = await networkConnection.viem.getPublicClient(); const normalLib = await networkConnection.viem.sendDeploymentTransaction( diff --git a/packages/hardhat-viem/test/hook-handlers/network.ts b/packages/hardhat-viem/test/hook-handlers/network.ts index f38cd0d96c7..716c7e31c5d 100644 --- a/packages/hardhat-viem/test/hook-handlers/network.ts +++ b/packages/hardhat-viem/test/hook-handlers/network.ts @@ -19,7 +19,7 @@ describe("hook-handlers/network", () => { const hre = await createHardhatRuntimeEnvironment({ plugins: [HardhatViem], }); - connection = await hre.network.connect(); + connection = await hre.network.create(); }); it("should be extended with viem", () => { diff --git a/packages/hardhat/src/internal/builtin-plugins/network-manager/hook-handlers/hre.ts b/packages/hardhat/src/internal/builtin-plugins/network-manager/hook-handlers/hre.ts index f061e35fec9..448ee6eef97 100644 --- a/packages/hardhat/src/internal/builtin-plugins/network-manager/hook-handlers/hre.ts +++ b/packages/hardhat/src/internal/builtin-plugins/network-manager/hook-handlers/hre.ts @@ -12,6 +12,14 @@ export default async (): Promise> => ({ let networkManager: NetworkManager | undefined; hre.network = { + async create(networkConnectionParams) { + if (networkManager === undefined) { + networkManager = await createNetworkManager(hre, context); + } + + return networkManager.create(networkConnectionParams); + }, + async connect(networkConnectionParams) { if (networkManager === undefined) { networkManager = await createNetworkManager(hre, context); @@ -19,6 +27,15 @@ export default async (): Promise> => ({ return networkManager.connect(networkConnectionParams); }, + + async getOrCreate(networkOrParams) { + if (networkManager === undefined) { + networkManager = await createNetworkManager(hre, context); + } + + return networkManager.getOrCreate(networkOrParams); + }, + async createServer(...params) { if (networkManager === undefined) { networkManager = await createNetworkManager(hre, context); @@ -27,6 +44,18 @@ export default async (): Promise> => ({ return networkManager.createServer(...params); }, }; + + // To avoid adding `wasConnectCalled` to the public interface of + // `NetworkManager`, we add this pass through method that is only + // called from the `main` function. + Object.defineProperty(hre.network, "wasConnectCalled", { + value: () => + networkManager !== undefined && + "wasConnectCalled" in networkManager && + typeof networkManager.wasConnectCalled === "function" && + networkManager.wasConnectCalled(), + enumerable: false, + }); }, }); diff --git a/packages/hardhat/src/internal/builtin-plugins/network-manager/network-manager.ts b/packages/hardhat/src/internal/builtin-plugins/network-manager/network-manager.ts index ecfcb356bc8..b4d1fcde7d1 100644 --- a/packages/hardhat/src/internal/builtin-plugins/network-manager/network-manager.ts +++ b/packages/hardhat/src/internal/builtin-plugins/network-manager/network-manager.ts @@ -12,6 +12,7 @@ import type { DefaultChainType, JsonRpcServer, NetworkConnection, + CachedNetworkConnectionParams, NetworkConnectionParams, NetworkManager, } from "../../../types/network.js"; @@ -59,10 +60,18 @@ export class NetworkManagerImplementation implements NetworkManager { readonly #projectRoot: string; readonly #verbosity: number; + #connectCalled = false; + #nextConnectionId = 0; readonly #contractDecoderMutex = new AsyncMutex(); #contractDecoder: ContractDecoder | undefined; + readonly #getOrCreateMutex = new AsyncMutex(); + readonly #getOrCreateCache = new Map< + string, + Map> + >(); + constructor( defaultNetwork: string, defaultChainType: DefaultChainType, @@ -87,9 +96,7 @@ export class NetworkManagerImplementation implements NetworkManager { this.#verbosity = verbosity; } - public async connect< - ChainTypeT extends ChainType | string = DefaultChainType, - >( + public async create( networkOrParams?: NetworkConnectionParams | string, ): Promise> { let networkName: string | undefined; @@ -117,6 +124,80 @@ export class NetworkManagerImplementation implements NetworkManager { return networkConnection as NetworkConnection; } + public async connect< + ChainTypeT extends ChainType | string = DefaultChainType, + >( + networkOrParams?: NetworkConnectionParams | string, + ): Promise> { + this.#connectCalled = true; + + return this.create(networkOrParams); + } + + public async getOrCreate< + ChainTypeT extends ChainType | string = DefaultChainType, + >( + networkOrParams?: CachedNetworkConnectionParams | string, + ): Promise> { + let network: string | undefined; + let chainType: ChainTypeT | undefined; + + if (typeof networkOrParams === "string") { + network = networkOrParams; + } else if (networkOrParams !== undefined) { + network = networkOrParams.network; + chainType = networkOrParams.chainType; + + if ("override" in networkOrParams) { + throw new HardhatError( + HardhatError.ERRORS.CORE.NETWORK.INVALID_CONFIG_OVERRIDE, + { + errors: "\t* Config overrides are not supported by getOrCreate.", + }, + ); + } + } + + const { resolvedNetworkName, resolvedChainType } = + this.#resolveNetworkAndChainType(network, chainType); + + const cached = this.#getOrCreateCache + .get(resolvedNetworkName) + ?.get(resolvedChainType); + if (cached !== undefined) { + /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions + -- Cast is safe: the cache keys guarantee the chain type matches */ + return cached as NetworkConnection; + } + + return this.#getOrCreateMutex.exclusiveRun(async () => { + // Double-check after acquiring the mutex — another call may have + // populated the cache while we were waiting. + const cachedAfterWaiting = this.#getOrCreateCache + .get(resolvedNetworkName) + ?.get(resolvedChainType); + if (cachedAfterWaiting !== undefined) { + /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions + -- Cast is safe: the cache keys guarantee the chain type matches */ + return cachedAfterWaiting as NetworkConnection; + } + + const connection = await this.create({ + network: resolvedNetworkName, + chainType: resolvedChainType, + }); + + let networkCache = this.#getOrCreateCache.get(resolvedNetworkName); + if (networkCache === undefined) { + networkCache = new Map(); + this.#getOrCreateCache.set(resolvedNetworkName, networkCache); + } + networkCache.set(resolvedChainType, connection); + + return connection; + }); + } + public async createServer< ChainTypeT extends ChainType | string = DefaultChainType, >( @@ -129,7 +210,7 @@ export class NetworkManagerImplementation implements NetworkManager { const insideDocker = await exists("/.dockerenv"); const hostname = _hostname ?? (insideDocker ? "0.0.0.0" : "127.0.0.1"); - const { provider } = await this.connect(networkOrParams); + const { provider } = await this.create(networkOrParams); return new JsonRpcServerImplementation({ hostname, @@ -138,30 +219,24 @@ export class NetworkManagerImplementation implements NetworkManager { }); } + /** + * Returns whether the deprecated `connect` method has been called on this + * instance. It is not on the public NetworkManager interface as it is only + * used by the CLI to print a deprecation warning at exit. + * + * @returns whether the deprecated `connect` method has ever been called + */ + public wasConnectCalled(): boolean { + return this.#connectCalled; + } + async #initializeNetworkConnection( networkName?: string, chainType?: ChainTypeT, networkConfigOverride?: NetworkConfigOverride, ): Promise> { - const resolvedNetworkName = networkName ?? this.#defaultNetwork; - const existingNetworkConfig = this.#networkConfigs[resolvedNetworkName]; - - if (existingNetworkConfig === undefined) { - throw new HardhatError( - HardhatError.ERRORS.CORE.NETWORK.NETWORK_NOT_FOUND, - { - networkName: resolvedNetworkName, - }, - ); - } - - /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- - * Type assertion is safe: defaultChainType ensures non-undefined, and the - * resolved value will be ChainTypeT (if provided) or a fallback that - * satisfies the ChainType | string constraint */ - const resolvedChainType = (chainType ?? - existingNetworkConfig.chainType ?? - this.#defaultChainType) as ChainTypeT; + const { resolvedNetworkName, resolvedChainType } = + this.#resolveNetworkAndChainType(networkName, chainType); const resolvedNetworkConfig = await this.#resolveNetworkConfig( resolvedNetworkName, @@ -287,9 +362,7 @@ export class NetworkManagerImplementation implements NetworkManager { allowUnlimitedContractSize: shouldEnableCoverage ? true : resolvedNetworkConfig.allowUnlimitedContractSize, - /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- - This case is safe because we have a check above */ - chainType: resolvedChainType as ChainType, + chainType: resolvedChainType, }, jsonRpcRequestWrapper, contractDecoder: this.#contractDecoder, @@ -387,7 +460,7 @@ export class NetworkManagerImplementation implements NetworkManager { throw new HardhatError( HardhatError.ERRORS.CORE.NETWORK.INVALID_CONFIG_OVERRIDE, { - errors: `\t* The chainType cannot be specified in config overrides. Pass it at the top level instead: hre.network.connect({ chainType: 'op' })`, + errors: `\t* The chainType cannot be specified in config overrides. Pass it at the top level instead: hre.network.create({ chainType: 'op' })`, }, ); } @@ -474,6 +547,36 @@ export class NetworkManagerImplementation implements NetworkManager { return resolvedNetworkConfigOverride; } + #resolveNetworkAndChainType< + ChainTypeT extends ChainType | string = DefaultChainType, + >( + network: string | undefined, + chainType: ChainTypeT | undefined, + ): { resolvedNetworkName: string; resolvedChainType: ChainTypeT } { + const resolvedNetworkName = network ?? this.#defaultNetwork; + const existingNetworkConfig = this.#networkConfigs[resolvedNetworkName]; + + if (existingNetworkConfig === undefined) { + throw new HardhatError( + HardhatError.ERRORS.CORE.NETWORK.NETWORK_NOT_FOUND, + { + networkName: resolvedNetworkName, + }, + ); + } + + const resolvedChainType = + chainType ?? existingNetworkConfig.chainType ?? this.#defaultChainType; + + return { + resolvedNetworkName, + /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions + -- The cast is safe because the fallback values are valid chain + types that match the caller's expected type at runtime. */ + resolvedChainType: resolvedChainType as ChainTypeT, + }; + } + async #getBuildInfosAndOutputsAsBuffers(): Promise< Array<{ buildInfo: Uint8Array; output: Uint8Array }> > { diff --git a/packages/hardhat/src/internal/builtin-plugins/node/task-action.ts b/packages/hardhat/src/internal/builtin-plugins/node/task-action.ts index 90d87857d3f..3fd5c22449a 100644 --- a/packages/hardhat/src/internal/builtin-plugins/node/task-action.ts +++ b/packages/hardhat/src/internal/builtin-plugins/node/task-action.ts @@ -106,10 +106,10 @@ const nodeAction: NewTaskActionFunction = async ( ); } - // NOTE: This is where we initialize the network; the connect method returns + // NOTE: This is where we initialize the network; the create method returns // a fully resolved networkConfig object which might be useful for display const { networkConfig, provider } = - await hre.network.connect(connectionParams); + await hre.network.create(connectionParams); assertHardhatInvariant( provider instanceof EdrProvider, diff --git a/packages/hardhat/src/internal/cli/main.ts b/packages/hardhat/src/internal/cli/main.ts index f235cee5916..ce247251d9a 100644 --- a/packages/hardhat/src/internal/cli/main.ts +++ b/packages/hardhat/src/internal/cli/main.ts @@ -236,6 +236,20 @@ export async function main( log("Error showing banner", bannerError); } } + + const deprecatedConnectWasCalled = Boolean( + "wasConnectCalled" in hre.network && + hre.network.wasConnectCalled !== undefined && + typeof hre.network.wasConnectCalled === "function" && + hre.network.wasConnectCalled(), + ); + + if (deprecatedConnectWasCalled) { + console.warn( + "WARNING: hre.network.connect() is deprecated and will be removed in a future version. " + + "Use hre.network.create() or hre.network.getOrCreate() instead.", + ); + } } catch (error) { ensureError(error); printErrorMessages(error, builtinGlobalOptions?.showStackTraces); diff --git a/packages/hardhat/src/types/network.ts b/packages/hardhat/src/types/network.ts index 43a26a4ed50..a054131574e 100644 --- a/packages/hardhat/src/types/network.ts +++ b/packages/hardhat/src/types/network.ts @@ -48,11 +48,59 @@ export interface NetworkConnectionParams< override?: NetworkConfigOverride; } +export interface CachedNetworkConnectionParams< + ChainTypeT extends ChainType | string = DefaultChainType, +> extends NetworkConnectionParams { + override?: never; +} + export interface NetworkManager { + /** + * Creates a new network connection based on the provided parameters. + * + * @param networkOrParams The network name or connection parameters. When + * omitted, the default network is used. + * + * @returns A new {@link NetworkConnection} for the specified network. + */ + create( + networkOrParams?: NetworkConnectionParams | string, + ): Promise>; + + /** + * Creates a new network connection based on the provided parameters. + * + * @deprecated Use {@link NetworkManager.create} or + * {@link NetworkManager.getOrCreate} instead. + * + * - {@link NetworkManager.create} always creates a new network instance. + * - {@link NetworkManager.getOrCreate} returns an existing instance if one exists. + * + * `connect` will be removed in a future version of Hardhat. + * + * @param networkOrParams The network name or connection parameters. When + * omitted, the default network is used. + * + * @returns A new {@link NetworkConnection} for the specified network. + */ connect( networkOrParams?: NetworkConnectionParams | string, ): Promise>; + /** + * Returns an existing network connection if one was previously created + * with the same network name and chain type. Creates a new one otherwise. + * + * @param networkOrParams The network name or connection parameters. When + * omitted, the default network is used. Overrides are not supported. + * + * @returns A {@link NetworkConnection} for the specified network, cached + * by network name and chain type. + */ + getOrCreate( + networkOrParams?: CachedNetworkConnectionParams | string, + ): Promise>; + /** * Spawns an Ethereum JSON-RPC server listening on HTTP and Websocket. * diff --git a/packages/hardhat/templates/hardhat-3/01-node-test-runner-viem/scripts/send-op-tx.ts b/packages/hardhat/templates/hardhat-3/01-node-test-runner-viem/scripts/send-op-tx.ts index bb738c5c86a..3fbd79f0d85 100644 --- a/packages/hardhat/templates/hardhat-3/01-node-test-runner-viem/scripts/send-op-tx.ts +++ b/packages/hardhat/templates/hardhat-3/01-node-test-runner-viem/scripts/send-op-tx.ts @@ -1,6 +1,6 @@ import { network } from "hardhat"; -const { viem } = await network.connect({ +const { viem } = await network.create({ network: "hardhatOp", chainType: "op", }); diff --git a/packages/hardhat/templates/hardhat-3/01-node-test-runner-viem/test/Counter.ts b/packages/hardhat/templates/hardhat-3/01-node-test-runner-viem/test/Counter.ts index 50c2713d8c1..af57b06c894 100644 --- a/packages/hardhat/templates/hardhat-3/01-node-test-runner-viem/test/Counter.ts +++ b/packages/hardhat/templates/hardhat-3/01-node-test-runner-viem/test/Counter.ts @@ -4,7 +4,7 @@ import { describe, it } from "node:test"; import { network } from "hardhat"; describe("Counter", async function () { - const { viem } = await network.connect(); + const { viem } = await network.create(); const publicClient = await viem.getPublicClient(); it("Should emit the Increment event when calling the inc() function", async function () { diff --git a/packages/hardhat/templates/hardhat-3/02-mocha-ethers/scripts/send-op-tx.ts b/packages/hardhat/templates/hardhat-3/02-mocha-ethers/scripts/send-op-tx.ts index c10a2360763..a615cbba96e 100644 --- a/packages/hardhat/templates/hardhat-3/02-mocha-ethers/scripts/send-op-tx.ts +++ b/packages/hardhat/templates/hardhat-3/02-mocha-ethers/scripts/send-op-tx.ts @@ -1,6 +1,6 @@ import { network } from "hardhat"; -const { ethers } = await network.connect({ +const { ethers } = await network.create({ network: "hardhatOp", chainType: "op", }); diff --git a/packages/hardhat/templates/hardhat-3/02-mocha-ethers/test/Counter.ts b/packages/hardhat/templates/hardhat-3/02-mocha-ethers/test/Counter.ts index f8c389864b3..a83c20222ec 100644 --- a/packages/hardhat/templates/hardhat-3/02-mocha-ethers/test/Counter.ts +++ b/packages/hardhat/templates/hardhat-3/02-mocha-ethers/test/Counter.ts @@ -1,7 +1,7 @@ import { expect } from "chai"; import { network } from "hardhat"; -const { ethers } = await network.connect(); +const { ethers } = await network.create(); describe("Counter", function () { it("Should emit the Increment event when calling the inc() function", async function () { diff --git a/packages/hardhat/test/internal/builtin-plugins/network-manager/edr/edr-provider.ts b/packages/hardhat/test/internal/builtin-plugins/network-manager/edr/edr-provider.ts index 0a70e4e61d2..e74160b3b07 100644 --- a/packages/hardhat/test/internal/builtin-plugins/network-manager/edr/edr-provider.ts +++ b/packages/hardhat/test/internal/builtin-plugins/network-manager/edr/edr-provider.ts @@ -38,7 +38,7 @@ describe("edr-provider", () => { describe("EdrProvider#request", () => { it("should return the expected response when the method is web3_clientVersion", async () => { - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const response = await provider.request({ method: "web3_clientVersion", @@ -56,7 +56,7 @@ describe("edr-provider", () => { { timeout: 1000 }, async () => { let eventEmitted = false; - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const eventPromise = once( provider, @@ -80,7 +80,7 @@ describe("edr-provider", () => { ); it("should return the expected response when the method is debug_traceTransaction", async () => { - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const accounts = await provider.request({ method: "eth_accounts", @@ -116,7 +116,7 @@ describe("edr-provider", () => { }); it("should return the expected response when the method is debug_traceCall", async () => { - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const accounts = await provider.request({ method: "eth_accounts", @@ -156,7 +156,7 @@ describe("edr-provider", () => { }); it("should throw a ProviderError if the params are invalid", async () => { - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); try { await provider.request({ @@ -175,7 +175,7 @@ describe("edr-provider", () => { }); it("should throw a ProviderError for any other type of failed response", async () => { - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const accounts = await provider.request({ method: "eth_accounts", @@ -215,7 +215,7 @@ describe("edr-provider", () => { }); it("should return account proof on local network", async () => { - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const accounts = await provider.request({ method: "eth_accounts", @@ -263,7 +263,7 @@ describe("edr-provider", () => { }); it("should return storage proof for contract on local network", async () => { - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); // Define arbitrary address and storage key const contractAddress = "0x1234567890123456789012345678901234567890"; @@ -326,7 +326,7 @@ describe("edr-provider", () => { }, }); - const { provider } = await forkedHre.network.connect("edrOptimism"); + const { provider } = await forkedHre.network.create("edrOptimism"); try { // WETH Optimism address @@ -371,7 +371,7 @@ describe("edr-provider", () => { }, }); - const { provider } = await forkedHre.network.connect("edrOptimism"); + const { provider } = await forkedHre.network.create("edrOptimism"); try { const accounts = await provider.request({ method: "eth_accounts" }); @@ -417,7 +417,7 @@ describe("edr-provider", () => { const notificationEventResults: string[] = []; const messageEventResults: string[] = []; - const { provider } = await hre.network.connect(); + const { provider } = await hre.network.create(); const notificationEventPromise = new Promise((resolve) => { provider.on("notification", ({ result }) => { @@ -458,7 +458,7 @@ describe("edr-provider", () => { describe("EdrProvider#close", () => { it("should not allow to make requests after closing", async () => { - const connection = await hre.network.connect(); + const connection = await hre.network.create(); await connection.provider.close(); @@ -472,7 +472,7 @@ describe("edr-provider", () => { }); it("should remove all listeners after closing", async () => { - const connection = await hre.network.connect(); + const connection = await hre.network.create(); connection.provider.on("notification", () => {}); assert.equal(connection.provider.listenerCount("notification"), 1); diff --git a/packages/hardhat/test/internal/builtin-plugins/network-manager/network-manager.ts b/packages/hardhat/test/internal/builtin-plugins/network-manager/network-manager.ts index d7caa49072d..f3bffd7e6b4 100644 --- a/packages/hardhat/test/internal/builtin-plugins/network-manager/network-manager.ts +++ b/packages/hardhat/test/internal/builtin-plugins/network-manager/network-manager.ts @@ -150,9 +150,9 @@ describe("NetworkManagerImplementation", () => { ); }); - describe("connect", () => { - it("should connect to the default network and chain type if none are provided", async () => { - const networkConnection = await networkManager.connect(); + describe("create", () => { + it("should create using the default network and chain type if none are provided", async () => { + const networkConnection = await networkManager.create(); assert.equal(networkConnection.networkName, "localhost"); assert.equal(networkConnection.chainType, GENERIC_CHAIN_TYPE); assert.deepEqual(networkConnection.networkConfig, { @@ -161,9 +161,9 @@ describe("NetworkManagerImplementation", () => { }); }); - it("should return the same networkConfig field references for two connect() calls without overrides", async () => { - const conn1 = await networkManager.connect(); - const conn2 = await networkManager.connect(); + it("should return the same networkConfig field references for two create() calls without overrides", async () => { + const conn1 = await networkManager.create(); + const conn2 = await networkManager.create(); assert.equal(conn1.networkConfig.type, conn2.networkConfig.type); @@ -180,12 +180,12 @@ describe("NetworkManagerImplementation", () => { } }); - it("should return the same networkConfig reference for two connect() calls that have the chain type defined in the config", async () => { - const conn1 = await networkManager.connect({ + it("should return the same networkConfig reference for two create() calls that have the chain type defined in the config", async () => { + const conn1 = await networkManager.create({ network: "edrNetwork", chainType: OPTIMISM_CHAIN_TYPE, }); - const conn2 = await networkManager.connect({ + const conn2 = await networkManager.create({ network: "edrNetwork", chainType: OPTIMISM_CHAIN_TYPE, }); @@ -194,7 +194,7 @@ describe("NetworkManagerImplementation", () => { }); it("should connect to the specified network and default chain type if none are provided and the network doesn't have a chain type", async () => { - const networkConnection = await networkManager.connect({ + const networkConnection = await networkManager.create({ network: "customNetwork", }); assert.equal(networkConnection.networkName, "customNetwork"); @@ -206,7 +206,7 @@ describe("NetworkManagerImplementation", () => { }); it("should connect to the specified network and use it's chain type if none is provided and the network has a chain type", async () => { - const networkConnection = await networkManager.connect({ + const networkConnection = await networkManager.create({ network: "myNetwork", }); assert.equal(networkConnection.networkName, "myNetwork"); @@ -215,7 +215,7 @@ describe("NetworkManagerImplementation", () => { }); it("should connect to the specified network and chain type", async () => { - const networkConnection = await networkManager.connect({ + const networkConnection = await networkManager.create({ network: "myNetwork", chainType: OPTIMISM_CHAIN_TYPE, }); @@ -229,7 +229,7 @@ describe("NetworkManagerImplementation", () => { chainId: 1234, // optional in the resolved config timeout: 30_000, // specific to http networks }; - let networkConnection = await networkManager.connect({ + let networkConnection = await networkManager.create({ network: "myNetwork", chainType: OPTIMISM_CHAIN_TYPE, override: httpConfigOverride, @@ -243,7 +243,7 @@ describe("NetworkManagerImplementation", () => { // Overriding the url is handled differently // so we need to test it separately - networkConnection = await networkManager.connect({ + networkConnection = await networkManager.create({ network: "myNetwork", chainType: OPTIMISM_CHAIN_TYPE, override: { @@ -266,7 +266,7 @@ describe("NetworkManagerImplementation", () => { }, }, }; - const networkConnection = await networkManager.connect({ + const networkConnection = await networkManager.create({ network: "edrNetwork", chainType: OPTIMISM_CHAIN_TYPE, override: edrConfigOverride, @@ -291,7 +291,7 @@ describe("NetworkManagerImplementation", () => { it("should throw an error if the specified network doesn't exist", async () => { await assertRejectsWithHardhatError( - networkManager.connect({ network: "unknownNetwork" }), + networkManager.create({ network: "unknownNetwork" }), HardhatError.ERRORS.CORE.NETWORK.NETWORK_NOT_FOUND, { networkName: "unknownNetwork" }, ); @@ -299,7 +299,7 @@ describe("NetworkManagerImplementation", () => { it("should throw an error if the specified network config override tries to change the network's type", async () => { await assertRejectsWithHardhatError( - networkManager.connect({ + networkManager.create({ network: "myNetwork", chainType: OPTIMISM_CHAIN_TYPE, /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions @@ -315,7 +315,7 @@ describe("NetworkManagerImplementation", () => { ); await assertRejectsWithHardhatError( - networkManager.connect({ + networkManager.create({ network: "myNetwork", chainType: OPTIMISM_CHAIN_TYPE, /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions @@ -333,7 +333,7 @@ describe("NetworkManagerImplementation", () => { it("should throw an error if the specified network config override is invalid", async () => { await assertRejectsWithHardhatError( - networkManager.connect({ + networkManager.create({ network: "myNetwork", chainType: OPTIMISM_CHAIN_TYPE, /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions @@ -351,7 +351,7 @@ describe("NetworkManagerImplementation", () => { it("should throw an error if the specified network config override tries to change the chainType", async () => { await assertRejectsWithHardhatError( - networkManager.connect({ + networkManager.create({ network: "edrNetwork", override: { /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions @@ -361,7 +361,7 @@ describe("NetworkManagerImplementation", () => { }), HardhatError.ERRORS.CORE.NETWORK.INVALID_CONFIG_OVERRIDE, { - errors: `\t* The chainType cannot be specified in config overrides. Pass it at the top level instead: hre.network.connect({ chainType: 'op' })`, + errors: `\t* The chainType cannot be specified in config overrides. Pass it at the top level instead: hre.network.create({ chainType: 'op' })`, }, ); }); @@ -369,7 +369,7 @@ describe("NetworkManagerImplementation", () => { describe("connecting with different chainType and hardfork configurations", () => { describe("network with no chainType or hardfork in config", () => { it("should connect with default chainType and latest hardfork", async () => { - const connection = await hre.network.connect({}); + const connection = await hre.network.create({}); assert.equal(connection.chainType, GENERIC_CHAIN_TYPE); assert.equal(connection.networkConfig.type, "edr-simulated"); @@ -381,7 +381,7 @@ describe("NetworkManagerImplementation", () => { }); it("should connect with specified chainType and its latest hardfork", async () => { - const connection = await hre.network.connect({ + const connection = await hre.network.create({ chainType: OPTIMISM_CHAIN_TYPE, }); @@ -395,7 +395,7 @@ describe("NetworkManagerImplementation", () => { }); it("should connect with specified chainType and hardfork override", async () => { - const connection = await hre.network.connect({ + const connection = await hre.network.create({ chainType: OPTIMISM_CHAIN_TYPE, override: { hardfork: OpHardforkName.HOLOCENE, @@ -413,7 +413,7 @@ describe("NetworkManagerImplementation", () => { it("should throw an error when overriding with invalid hardfork for the chainType", async () => { await assertRejectsWithHardhatError( - hre.network.connect({ + hre.network.create({ chainType: OPTIMISM_CHAIN_TYPE, override: { hardfork: L1HardforkName.LONDON, @@ -431,7 +431,7 @@ describe("NetworkManagerImplementation", () => { ); await assertRejectsWithHardhatError( - hre.network.connect({ + hre.network.create({ override: { hardfork: OpHardforkName.HOLOCENE, }, @@ -462,7 +462,7 @@ describe("NetworkManagerImplementation", () => { }); it("should connect with default chainType and configured hardfork", async () => { - const connection = await hre.network.connect({}); + const connection = await hre.network.create({}); assert.equal(connection.chainType, GENERIC_CHAIN_TYPE); assert.equal(connection.networkConfig.type, "edr-simulated"); @@ -474,7 +474,7 @@ describe("NetworkManagerImplementation", () => { }); it("should connect with overridden valid hardfork for same chainType", async () => { - const connection = await hre.network.connect({ + const connection = await hre.network.create({ override: { hardfork: L1HardforkName.SHANGHAI, }, @@ -491,7 +491,7 @@ describe("NetworkManagerImplementation", () => { it("should throw an error when overriding with invalid hardfork", async () => { await assertRejectsWithHardhatError( - hre.network.connect({ + hre.network.create({ override: { hardfork: OpHardforkName.HOLOCENE, }, @@ -510,7 +510,7 @@ describe("NetworkManagerImplementation", () => { it("should throw an error when changing chainType without overriding hardfork", async () => { await assertRejectsWithHardhatError( - hre.network.connect({ + hre.network.create({ chainType: OPTIMISM_CHAIN_TYPE, }), HardhatError.ERRORS.CORE.NETWORK.INVALID_CONFIG_OVERRIDE, @@ -539,7 +539,7 @@ describe("NetworkManagerImplementation", () => { }); it("should connect with configured chainType and its latest hardfork", async () => { - const connection = await hre.network.connect({}); + const connection = await hre.network.create({}); assert.equal(connection.chainType, OPTIMISM_CHAIN_TYPE); assert.equal(connection.networkConfig.type, "edr-simulated"); @@ -551,7 +551,7 @@ describe("NetworkManagerImplementation", () => { }); it("should connect with valid hardfork override for configured chainType", async () => { - const connection = await hre.network.connect({ + const connection = await hre.network.create({ override: { hardfork: OpHardforkName.HOLOCENE, }, @@ -568,7 +568,7 @@ describe("NetworkManagerImplementation", () => { it("should throw an error when overriding with invalid hardfork for configured chainType", async () => { await assertRejectsWithHardhatError( - hre.network.connect({ + hre.network.create({ override: { hardfork: L1HardforkName.LONDON, }, @@ -586,7 +586,7 @@ describe("NetworkManagerImplementation", () => { }); it("should connect when changing to different chainType with its latest hardfork", async () => { - const connection = await hre.network.connect({ + const connection = await hre.network.create({ chainType: GENERIC_CHAIN_TYPE, }); @@ -614,7 +614,7 @@ describe("NetworkManagerImplementation", () => { }); it("should connect with configured chainType and hardfork", async () => { - const connection = await hre.network.connect({}); + const connection = await hre.network.create({}); assert.equal(connection.chainType, OPTIMISM_CHAIN_TYPE); assert.equal(connection.networkConfig.type, "edr-simulated"); @@ -626,7 +626,7 @@ describe("NetworkManagerImplementation", () => { }); it("should connect with valid hardfork override for configured chainType", async () => { - const connection = await hre.network.connect({ + const connection = await hre.network.create({ override: { hardfork: OpHardforkName.FJORD, }, @@ -640,7 +640,7 @@ describe("NetworkManagerImplementation", () => { it("should throw an error when overriding with invalid hardfork for configured chainType", async () => { await assertRejectsWithHardhatError( - hre.network.connect({ + hre.network.create({ override: { hardfork: L1HardforkName.LONDON, }, @@ -659,7 +659,7 @@ describe("NetworkManagerImplementation", () => { it("should throw an error when changing chainType without hardfork override", async () => { await assertRejectsWithHardhatError( - hre.network.connect({ + hre.network.create({ chainType: GENERIC_CHAIN_TYPE, }), HardhatError.ERRORS.CORE.NETWORK.INVALID_CONFIG_OVERRIDE, @@ -688,7 +688,7 @@ describe("NetworkManagerImplementation", () => { hre.hooks.registerHandlers("network", networkHooks); - await networkManager.connect(); + await networkManager.create(); hre.hooks.unregisterHandlers("network", networkHooks); @@ -698,7 +698,7 @@ describe("NetworkManagerImplementation", () => { describe("types", () => { it("should create a NetworkConnection with the default chain type when no chain type is provided", async () => { - const networkConnection = await networkManager.connect({ + const networkConnection = await networkManager.create({ network: "localhost", }); expectTypeOf(networkConnection).toEqualTypeOf< @@ -707,7 +707,7 @@ describe("NetworkManagerImplementation", () => { }); it("should create a NetworkConnection with the provided chain type", async () => { - const networkConnection = await networkManager.connect({ + const networkConnection = await networkManager.create({ network: "localhost", chainType: L1_CHAIN_TYPE, }); @@ -842,7 +842,7 @@ describe("NetworkManagerImplementation", () => { }); it("should keep extensions to network config that plugins have added", async () => { - const networkConnection = await networkManager.connect({ + const networkConnection = await networkManager.create({ network: "pluginExtendedNetwork", }); @@ -852,7 +852,7 @@ describe("NetworkManagerImplementation", () => { }); it("should re-extend config when a user override is provided", async () => { - const networkConnection = await networkManager.connect({ + const networkConnection = await networkManager.create({ network: "pluginExtendedNetwork", override: { timeout: 12, @@ -865,7 +865,7 @@ describe("NetworkManagerImplementation", () => { }); it("should re-extend config based on user provided values", async () => { - const networkConnection = await networkManager.connect({ + const networkConnection = await networkManager.create({ network: "pluginExtendedNetwork", /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- to enable the test of plugin extension. */ @@ -921,15 +921,15 @@ describe("NetworkManagerImplementation", () => { }); it("should not call resolveUserConfig when connecting without overrides", async () => { - await networkManager.connect(); - await networkManager.connect(); + await networkManager.create(); + await networkManager.create(); // Note: this is 1 and not 0 because there's the HRE creation's config // resolution assert.equal(resolveUserConfigCallCount, 1); }); it("should call resolveUserConfig when connecting with overrides", async () => { - await networkManager.connect({ + await networkManager.create({ network: "localhost", override: { timeout: 5000 }, }); @@ -1013,7 +1013,7 @@ describe("NetworkManagerImplementation", () => { it("should throw INVALID_CONFIG_OVERRIDE when resolved config validation returns errors", async () => { await assertRejectsWithHardhatError( - networkManager.connect({ + networkManager.create({ network: "localhost", override: { timeout: 99999, @@ -1027,6 +1027,130 @@ describe("NetworkManagerImplementation", () => { }); }); + describe("connect", () => { + it("should behave the same as create", async () => { + const connectConn = await networkManager.connect("myNetwork"); + const createConn = await networkManager.create("myNetwork"); + + assert.equal(connectConn.networkName, createConn.networkName); + assert.equal(connectConn.chainType, createConn.chainType); + assert.equal(connectConn.chainType, OPTIMISM_CHAIN_TYPE); + }); + + it("should record that connect was called", async () => { + /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions + -- Accessing internal method not on the NetworkManager interface */ + const impl = networkManager as unknown as NetworkManagerImplementation; + + assert.equal(impl.wasConnectCalled(), false); + + await networkManager.connect("myNetwork"); + + assert.equal(impl.wasConnectCalled(), true); + }); + }); + + describe("getOrCreate", () => { + it("should use the default network when none is provided", async () => { + const conn = await networkManager.getOrCreate(); + + assert.equal(conn.networkName, "localhost"); + }); + + it("should use the default chain type when none is provided", async () => { + const conn = await networkManager.getOrCreate(); + + assert.equal(conn.chainType, GENERIC_CHAIN_TYPE); + }); + + it("should return the same connection for repeated calls with no arguments", async () => { + const conn1 = await networkManager.getOrCreate(); + const conn2 = await networkManager.getOrCreate(); + + assert.equal(conn1, conn2); + }); + + it("should return the same connection for repeated calls with the same network", async () => { + const conn1 = await networkManager.getOrCreate("customNetwork"); + const conn2 = await networkManager.getOrCreate("customNetwork"); + + assert.equal(conn1, conn2); + }); + + it("should return the same connection for repeated calls with the same network and chainType", async () => { + const conn1 = await networkManager.getOrCreate({ + network: "myNetwork", + chainType: OPTIMISM_CHAIN_TYPE, + }); + const conn2 = await networkManager.getOrCreate({ + network: "myNetwork", + chainType: OPTIMISM_CHAIN_TYPE, + }); + + assert.equal(conn1, conn2); + }); + + it("should return different connections for different networks", async () => { + const conn1 = await networkManager.getOrCreate("localhost"); + const conn2 = await networkManager.getOrCreate("customNetwork"); + + assert.notEqual(conn1, conn2); + }); + + it("should return the same connection when the config chainType matches an explicit chainType", async () => { + // myNetwork has chainType: OPTIMISM_CHAIN_TYPE from the config + const connImplicit = await networkManager.getOrCreate("myNetwork"); + const connExplicit = await networkManager.getOrCreate({ + network: "myNetwork", + chainType: OPTIMISM_CHAIN_TYPE, + }); + + assert.equal(connImplicit.chainType, OPTIMISM_CHAIN_TYPE); + assert.equal(connImplicit, connExplicit); + }); + + it("should return different connections when the config chainType differs from an explicit chainType", async () => { + // myNetwork has chainType: OPTIMISM_CHAIN_TYPE from the config + const connDefault = await networkManager.getOrCreate("myNetwork"); + const connGeneric = await networkManager.getOrCreate({ + network: "myNetwork", + chainType: GENERIC_CHAIN_TYPE, + }); + + assert.equal(connDefault.chainType, OPTIMISM_CHAIN_TYPE); + assert.equal(connGeneric.chainType, GENERIC_CHAIN_TYPE); + assert.notEqual(connDefault, connGeneric); + }); + + it("should return different connections for the same network with different chainTypes", async () => { + const conn1 = await networkManager.getOrCreate({ + network: "myNetwork", + chainType: OPTIMISM_CHAIN_TYPE, + }); + const conn2 = await networkManager.getOrCreate({ + network: "myNetwork", + chainType: GENERIC_CHAIN_TYPE, + }); + + assert.notEqual(conn1, conn2); + }); + + it("should throw an error if an override is provided", async () => { + await assertRejectsWithHardhatError( + /* eslint-disable-next-line @typescript-eslint/consistent-type-assertions + -- Cast to simulate a JS caller bypassing the type system */ + networkManager.getOrCreate({ + network: "localhost", + override: { url: "http://localhost:8545" }, + } as any), + HardhatError.ERRORS.CORE.NETWORK.INVALID_CONFIG_OVERRIDE, + { + errors: "\t* Config overrides are not supported by getOrCreate.", + }, + ); + }); + }); + describe("createServer", function () { it("should throw an error if the network type is not edr-simulated", async () => { await assertRejectsWithHardhatError( @@ -1053,7 +1177,7 @@ describe("NetworkManagerImplementation", () => { const { address, port } = await server.listen(); try { - const { provider } = await networkManager.connect({ + const { provider } = await networkManager.create({ network: "localhost", override: { url: `http://${address}:${port}` }, }); @@ -1072,7 +1196,7 @@ describe("NetworkManagerImplementation", () => { const { address, port } = await server.listen(); try { - const { provider } = await networkManager.connect({ + const { provider } = await networkManager.create({ network: "localhost", override: { url: `http://${address}:${port}` }, }); @@ -1095,7 +1219,7 @@ describe("NetworkManagerImplementation", () => { hre.hooks.registerHandlers("network", networkHooks); - const networkConnection = await networkManager.connect(); + const networkConnection = await networkManager.create(); await networkConnection.close(); hre.hooks.unregisterHandlers("network", networkHooks); @@ -1122,7 +1246,7 @@ describe("NetworkManagerImplementation", () => { hre.hooks.registerHandlers("network", networkHooks); - const connection = await networkManager.connect(); + const connection = await networkManager.create(); // This will fail because we don't have a local node running // but we don't care about the result, we just want to trigger the hook try { @@ -3146,11 +3270,11 @@ describe("NetworkManagerImplementation", () => { it("should create the ContractDecoder only once across multiple EDR connections", async (t) => { const spy = t.mock.method(EdrProvider, "createContractDecoder"); - await networkManager.connect({ + await networkManager.create({ network: "edrNetwork", }); - await networkManager.connect({ + await networkManager.create({ network: "edrNetwork", }); diff --git a/packages/hardhat/test/internal/builtin-plugins/network-manager/request-handlers/e2e.ts b/packages/hardhat/test/internal/builtin-plugins/network-manager/request-handlers/e2e.ts index 1c60ea00941..a28a64f8f3a 100644 --- a/packages/hardhat/test/internal/builtin-plugins/network-manager/request-handlers/e2e.ts +++ b/packages/hardhat/test/internal/builtin-plugins/network-manager/request-handlers/e2e.ts @@ -41,7 +41,7 @@ describe("request-handlers - e2e", () => { }, ); - const connection = await hre.network.connect({ network: "localhost" }); + const connection = await hre.network.create({ network: "localhost" }); const res = await connection.provider.request({ method: "eth_sendTransaction", @@ -102,7 +102,7 @@ describe("request-handlers - e2e", () => { }, ); - const connection = await hre.network.connect({ network: "localhost" }); + const connection = await hre.network.create({ network: "localhost" }); const res = await connection.provider.request({ method: "eth_sendTransaction", @@ -171,7 +171,7 @@ describe("request-handlers - e2e", () => { }, ); - const connection = await hre.network.connect({ + const connection = await hre.network.create({ network: "localhost", }); @@ -241,7 +241,7 @@ describe("request-handlers - e2e", () => { }, ); - const connection = await hre.network.connect({ + const connection = await hre.network.create({ network: "localhost", }); diff --git a/packages/hardhat/test/internal/builtin-plugins/node/json-rpc/server.ts b/packages/hardhat/test/internal/builtin-plugins/node/json-rpc/server.ts index 0bfd6e0267c..0d7f920abdf 100644 --- a/packages/hardhat/test/internal/builtin-plugins/node/json-rpc/server.ts +++ b/packages/hardhat/test/internal/builtin-plugins/node/json-rpc/server.ts @@ -20,7 +20,7 @@ describe("JSON-RPC server", function () { const hostname = (await exists("/.dockerenv")) ? "0.0.0.0" : "127.0.0.1"; const port = 8545; - const connection = await hre.network.connect(); + const connection = await hre.network.create(); const server = new JsonRpcServerImplementation({ hostname, port, diff --git a/packages/ignition-core/test-integrations/helpers/create-hre.ts b/packages/ignition-core/test-integrations/helpers/create-hre.ts index f1335fc972b..bb86059a6cc 100644 --- a/packages/ignition-core/test-integrations/helpers/create-hre.ts +++ b/packages/ignition-core/test-integrations/helpers/create-hre.ts @@ -9,7 +9,7 @@ import { EIP1193JsonRpcClient } from "../../src/internal/execution/jsonrpc-clien export async function createConnection(): Promise { const hre = await createHre(); - const connection = await hre.network.connect(); + const connection = await hre.network.create(); await connection.provider.request({ method: "evm_setAutomine", @@ -32,7 +32,7 @@ export async function createHre(): Promise { process.cwd(), ); - const connection = await hre.network.connect(); + const connection = await hre.network.create(); await connection.provider.request({ method: "evm_setAutomine", @@ -55,7 +55,7 @@ export async function createClient( connection: NetworkConnection; }> { const hre = await createHre(); - const connection = await hre.network.connect(); + const connection = await hre.network.create(); const client = new EIP1193JsonRpcClient(connection.provider, config); return { client,