From 9d27249c86bb8e4224589e1ac85219b90c1ba34d Mon Sep 17 00:00:00 2001 From: John Kane Date: Tue, 27 Aug 2024 09:32:09 +0100 Subject: [PATCH 1/4] feat: add skeleton artifacts plugin Add an in-built plugin that `extends` the HRE with an `artifacts` implementation based on the v2 interface. --- .../internal/artifacts/artifacts-manager.ts | 76 ++++++ .../artifacts/hookHandlers/hre.ts | 13 + .../builtin-plugins/artifacts/index.ts | 11 + .../artifacts/type-extensions.ts | 7 + .../src/internal/builtin-plugins/index.ts | 4 +- v-next/hardhat/src/internal/core/hre.ts | 2 + v-next/hardhat/src/types/artifacts.ts | 237 ++++++++++++++++++ 7 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 v-next/hardhat/src/internal/artifacts/artifacts-manager.ts create mode 100644 v-next/hardhat/src/internal/builtin-plugins/artifacts/hookHandlers/hre.ts create mode 100644 v-next/hardhat/src/internal/builtin-plugins/artifacts/index.ts create mode 100644 v-next/hardhat/src/internal/builtin-plugins/artifacts/type-extensions.ts create mode 100644 v-next/hardhat/src/types/artifacts.ts diff --git a/v-next/hardhat/src/internal/artifacts/artifacts-manager.ts b/v-next/hardhat/src/internal/artifacts/artifacts-manager.ts new file mode 100644 index 0000000000..cc9ca83839 --- /dev/null +++ b/v-next/hardhat/src/internal/artifacts/artifacts-manager.ts @@ -0,0 +1,76 @@ +import type { + Artifact, + ArtifactsManager, + BuildInfo, + CompilerInput, + CompilerOutput, +} from "../../types/artifacts.js"; + +import { HardhatError } from "@ignored/hardhat-vnext-errors"; + +export class ArtifactsManagerImplementation implements ArtifactsManager { + public readArtifact( + _contractNameOrFullyQualifiedName: string, + ): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in fake artifacts manager", + }); + } + + public artifactExists( + _contractNameOrFullyQualifiedName: string, + ): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in fake artifacts manager", + }); + } + + public getAllFullyQualifiedNames(): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in fake artifacts manager", + }); + } + + public getBuildInfo( + _fullyQualifiedName: string, + ): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in fake artifacts manager", + }); + } + + public getArtifactPaths(): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in fake artifacts manager", + }); + } + + public getBuildInfoPaths(): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in fake artifacts manager", + }); + } + + public saveArtifact(_artifact: Artifact): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in fake artifacts manager", + }); + } + + public saveBuildInfo( + _solcVersion: string, + _solcLongVersion: string, + _input: CompilerInput, + _output: CompilerOutput, + ): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in fake artifacts manager", + }); + } + + public getArtifactPath(_fullyQualifiedName: string): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in fake artifacts manager", + }); + } +} diff --git a/v-next/hardhat/src/internal/builtin-plugins/artifacts/hookHandlers/hre.ts b/v-next/hardhat/src/internal/builtin-plugins/artifacts/hookHandlers/hre.ts new file mode 100644 index 0000000000..9ec240e303 --- /dev/null +++ b/v-next/hardhat/src/internal/builtin-plugins/artifacts/hookHandlers/hre.ts @@ -0,0 +1,13 @@ +import type { HardhatRuntimeEnvironmentHooks } from "../../../../types/hooks.js"; + +import { ArtifactsManagerImplementation } from "../../../artifacts/artifacts-manager.js"; + +export default async (): Promise> => { + const handlers: Partial = { + created: async (_context, hre): Promise => { + hre.artifacts = new ArtifactsManagerImplementation(); + }, + }; + + return handlers; +}; diff --git a/v-next/hardhat/src/internal/builtin-plugins/artifacts/index.ts b/v-next/hardhat/src/internal/builtin-plugins/artifacts/index.ts new file mode 100644 index 0000000000..2b2b6d3ff0 --- /dev/null +++ b/v-next/hardhat/src/internal/builtin-plugins/artifacts/index.ts @@ -0,0 +1,11 @@ +import type { HardhatPlugin } from "../../../types/plugins.js"; +import "./type-extensions.js"; + +const hardhatPlugin: HardhatPlugin = { + id: "artifacts", + hookHandlers: { + hre: import.meta.resolve("./hookHandlers/hre.js"), + }, +}; + +export default hardhatPlugin; diff --git a/v-next/hardhat/src/internal/builtin-plugins/artifacts/type-extensions.ts b/v-next/hardhat/src/internal/builtin-plugins/artifacts/type-extensions.ts new file mode 100644 index 0000000000..d8f5b3b676 --- /dev/null +++ b/v-next/hardhat/src/internal/builtin-plugins/artifacts/type-extensions.ts @@ -0,0 +1,7 @@ +import type { ArtifactsManager } from "../../../types/artifacts.js"; + +declare module "../../../types/hre.js" { + interface HardhatRuntimeEnvironment { + artifacts: ArtifactsManager; + } +} diff --git a/v-next/hardhat/src/internal/builtin-plugins/index.ts b/v-next/hardhat/src/internal/builtin-plugins/index.ts index 750fc7cc5e..de3bb6432e 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/index.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/index.ts @@ -1,5 +1,6 @@ import type { HardhatPlugin } from "../../types/plugins.js"; +import artifacts from "./artifacts/index.js"; import clean from "./clean/index.js"; import console from "./console/index.js"; import networkManager from "./network-manager/index.js"; @@ -8,14 +9,15 @@ import solidity from "./solidity/index.js"; // Note: When importing a plugin, you have to export its types, so that its // type extensions, if any, also get loaded. +export type * from "./artifacts/index.js"; export type * from "./solidity/index.js"; export type * from "./network-manager/index.js"; export type * from "./clean/index.js"; export type * from "./console/index.js"; -export type * from "./network-manager/index.js"; export type * from "./run/index.js"; export const builtinPlugins: HardhatPlugin[] = [ + artifacts, solidity, networkManager, clean, diff --git a/v-next/hardhat/src/internal/core/hre.ts b/v-next/hardhat/src/internal/core/hre.ts index 010fe15f5c..9cdaaabc82 100644 --- a/v-next/hardhat/src/internal/core/hre.ts +++ b/v-next/hardhat/src/internal/core/hre.ts @@ -1,4 +1,5 @@ import type { UnsafeHardhatRuntimeEnvironmentOptions } from "./types.js"; +import type { ArtifactsManager } from "../../types/artifacts.js"; import type { HardhatUserConfig, HardhatConfig, @@ -40,6 +41,7 @@ export class HardhatRuntimeEnvironmentImplementation // here, because it's added by a plugin. But as that plugin is builtin, its // type extensions also affect this module. public network!: NetworkManager; + public artifacts!: ArtifactsManager; public static async create( inputUserConfig: HardhatUserConfig, diff --git a/v-next/hardhat/src/types/artifacts.ts b/v-next/hardhat/src/types/artifacts.ts new file mode 100644 index 0000000000..ac75d684ce --- /dev/null +++ b/v-next/hardhat/src/types/artifacts.ts @@ -0,0 +1,237 @@ +/** + * WARNING: This is a placholder, while the build system is being implemented. + * This ArtifactsManager will be replaced, but the capabilities are similar + * enough to aid development. + * + * TODO: Replace this with the real ArtifactsManager. + * + * The ArtifactsManager is responsible for reading and writing artifacts from + * the Hardhat build system. + */ +export interface ArtifactsManager { + /** + * Reads an artifact. + * + * @param contractNameOrFullyQualifiedName The name of the contract. + * It can be a contract bare contract name (e.g. "Token") if it's + * unique in your project, or a fully qualified contract name + * (e.g. "contract/token.sol:Token") otherwise. + * + * @throws Throws an error if a non-unique contract name is used, + * indicating which fully qualified names can be used instead. + */ + readArtifact(contractNameOrFullyQualifiedName: string): Promise; + + /** + * Returns true if an artifact exists. + * + * This function doesn't throw if the name is not unique. + * + * @param contractNameOrFullyQualifiedName Contract or fully qualified name. + * + */ + artifactExists(contractNameOrFullyQualifiedName: string): Promise; + + /** + * Returns an array with the fully qualified names of all the artifacts. + */ + getAllFullyQualifiedNames(): Promise; + + /** + * Returns the BuildInfo associated with the solc run that compiled a + * contract. + * + * Note that if your contract hasn't been compiled with solc this method + * can return undefined. + */ + getBuildInfo(fullyQualifiedName: string): Promise; + + /** + * Returns an array with the absolute paths of all the existing artifacts. + * + * Note that there's an artifact per contract. + */ + getArtifactPaths(): Promise; + + /** + * Returns an array with the absolute paths of all the existing build infos. + * + * Note that there's one build info per run of solc, so they can be shared + * by different contracts. + */ + getBuildInfoPaths(): Promise; + + /** + * Saves a contract's artifact and debug file. + * + * @param artifact The artifact object. + */ + saveArtifact(artifact: Artifact): Promise; + + /** + * Saves the build info associated to a solc run. + * + * @param solcVersion The semver-compatible version number. + * @param solcLongVersion The full solc version. + * @param input The compiler input. + * @param output The compiler output. + */ + saveBuildInfo( + solcVersion: string, + solcLongVersion: string, + input: CompilerInput, + output: CompilerOutput, + ): Promise; + + /** + * Returns the absolute path to the given artifact. + * + * @param fullyQualifiedName The FQN of the artifact. + */ + getArtifactPath(contractNameOrFullyQualifiedName: string): Promise; +} + +/** + * WARNING: This is a placholder, while the build system is being implemented. + */ +export type Abi = readonly any[] | any[]; + +/** + * WARNING: This is a placholder, while the build system is being implemented. + * + * An artifact representing the compilation output of a contract. + * + * This file has just enough information to deploy the contract and interact + * with an already deployed instance of it. + * + * For debugging information and other extra information, you should look for + * its companion DebugFile, which should be stored right next to it. + * + * Note that DebugFiles are only generated for Solidity contracts. + */ +export interface Artifact { + _format: string; + contractName: string; + sourceName: string; + abi: AbiT; + bytecode: string; // "0x"-prefixed hex string + deployedBytecode: string; // "0x"-prefixed hex string + linkReferences: LinkReferences; + deployedLinkReferences: LinkReferences; +} + +/** + * WARNING: This is a placholder, while the build system is being implemented. + * + * A BuildInfo is a file that contains all the information of a solc run. It + * includes all the necessary information to recreate that exact same run, and + * all of its output. + */ +export interface BuildInfo { + _format: string; + id: string; + solcVersion: string; + solcLongVersion: string; + input: CompilerInput; + output: CompilerOutput; +} + +/** + * WARNING: This is a placholder, while the build system is being implemented. + */ +export interface LinkReferences { + [libraryFileName: string]: { + [libraryName: string]: Array<{ length: number; start: number }>; + }; +} + +/** + * WARNING: This is a placholder, while the build system is being implemented. + */ +export interface CompilerInput { + language: string; + sources: { [sourceName: string]: { content: string } }; + settings: { + viaIR?: boolean; + optimizer: { + runs?: number; + enabled?: boolean; + details?: { + yulDetails: { + optimizerSteps: string; + }; + }; + }; + metadata?: { useLiteralContent: boolean }; + outputSelection: { + [sourceName: string]: { + [contractName: string]: string[]; + }; + }; + evmVersion?: string; + libraries?: { + [libraryFileName: string]: { + [libraryName: string]: string; + }; + }; + remappings?: string[]; + }; +} + +/** + * WARNING: This is a placholder, while the build system is being implemented. + */ +export interface CompilerOutputContract { + abi: any; + evm: { + bytecode: CompilerOutputBytecode; + deployedBytecode: CompilerOutputBytecode; + methodIdentifiers: { + [methodSignature: string]: string; + }; + }; +} + +/** + * WARNING: This is a placholder, while the build system is being implemented. + */ +export interface CompilerOutput { + sources: CompilerOutputSources; + contracts: { + [sourceName: string]: { + [contractName: string]: CompilerOutputContract; + }; + }; +} + +/** + * WARNING: This is a placholder, while the build system is being implemented. + */ +export interface CompilerOutputSource { + id: number; + ast: any; +} + +/** + * WARNING: This is a placholder, while the build system is being implemented. + */ +export interface CompilerOutputSources { + [sourceName: string]: CompilerOutputSource; +} + +/** + * WARNING: This is a placholder, while the build system is being implemented. + */ +export interface CompilerOutputBytecode { + object: string; + opcodes: string; + sourceMap: string; + linkReferences: { + [sourceName: string]: { + [libraryName: string]: Array<{ start: number; length: 20 }>; + }; + }; + immutableReferences?: { + [key: string]: Array<{ start: number; length: number }>; + }; +} From 4f99632e9a6cebc85d868924ffee65548ceba2e2 Mon Sep 17 00:00:00 2001 From: John Kane Date: Tue, 27 Aug 2024 10:46:41 +0100 Subject: [PATCH 2/4] test: add example test of mocking hre artifacts We add a `createMockHardhatRuntimeEnvironment` that overrides the standard artifacts built-in plugin and substitutes in a mock version that can be leveraged in tests and development. There is a supporting test to show the usage of the mocked artifacts manager. --- ...xample-mock-artifacts-plugin-using-test.ts | 54 +++++++++ ...create-mock-hardhat-runtime-environment.ts | 40 +++++++ .../test-helpers/mock-artifacts-manager.ts | 104 ++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 v-next/hardhat/test/internal/example-mock-artifacts-plugin-using-test.ts create mode 100644 v-next/hardhat/test/test-helpers/create-mock-hardhat-runtime-environment.ts create mode 100644 v-next/hardhat/test/test-helpers/mock-artifacts-manager.ts diff --git a/v-next/hardhat/test/internal/example-mock-artifacts-plugin-using-test.ts b/v-next/hardhat/test/internal/example-mock-artifacts-plugin-using-test.ts new file mode 100644 index 0000000000..05d1a4275a --- /dev/null +++ b/v-next/hardhat/test/internal/example-mock-artifacts-plugin-using-test.ts @@ -0,0 +1,54 @@ +import type { Artifact } from "../../src/types/artifacts.js"; +import type { HardhatRuntimeEnvironment } from "../../src/types/hre.js"; +import type { HardhatPlugin } from "../../src/types/plugins.js"; + +import assert from "node:assert/strict"; +import { describe, it } from "node:test"; + +import { task } from "../../src/config.js"; +import { createMockHardhatRuntimeEnvironment } from "../test-helpers/create-mock-hardhat-runtime-environment.js"; + +// TODO: This test is an example and should be removed with the completion of +// the build system and the artifacts plugin. +describe("createMockHardhatRuntimeEnvironment", () => { + it("should allow plugins that leverage the artifact hre object", async () => { + // arrange + const exampleArtifact: Artifact = { + _format: "hh-sol-artifact-1", + contractName: "MyContract", + sourceName: "source.sol", + abi: [], + bytecode: "0x", + linkReferences: {}, + deployedBytecode: "0x", + deployedLinkReferences: {}, + }; + + const myPlugin: HardhatPlugin = { + id: "my-plugin", + tasks: [ + task("hello-artifact-using-world", "Tests artifact loading") + .setAction(async ({}, hre: HardhatRuntimeEnvironment) => { + return hre.artifacts.readArtifact("MyContract"); + }) + .build(), + ], + }; + + const mockHre = await createMockHardhatRuntimeEnvironment({ + plugins: [myPlugin], + }); + + await mockHre.artifacts.saveArtifact(exampleArtifact); + + // act + const helloArtifactUsingWorld = mockHre.tasks.getTask( + "hello-artifact-using-world", + ); + + const result = await helloArtifactUsingWorld.run({}); + + // Assert + assert.equal(result, exampleArtifact); + }); +}); diff --git a/v-next/hardhat/test/test-helpers/create-mock-hardhat-runtime-environment.ts b/v-next/hardhat/test/test-helpers/create-mock-hardhat-runtime-environment.ts new file mode 100644 index 0000000000..c67458e154 --- /dev/null +++ b/v-next/hardhat/test/test-helpers/create-mock-hardhat-runtime-environment.ts @@ -0,0 +1,40 @@ +import type { HardhatUserConfig } from "../../src/config.js"; +import type { UnsafeHardhatRuntimeEnvironmentOptions } from "../../src/internal/core/types.js"; +import type { GlobalOptions } from "../../src/types/global-options.js"; +import type { HardhatRuntimeEnvironment } from "../../src/types/hre.js"; +import type { HardhatPlugin } from "../../src/types/plugins.js"; + +import "../../src/internal/builtin-plugins/artifacts/type-extensions.js"; + +import { createHardhatRuntimeEnvironment } from "../../src/hre.js"; +import artifacts from "../../src/internal/builtin-plugins/artifacts/index.js"; + +import { MockArtifactsManager } from "./mock-artifacts-manager.js"; + +export async function createMockHardhatRuntimeEnvironment( + config: HardhatUserConfig, + userProvidedGlobalOptions: Partial = {}, + projectRoot?: string, + unsafeOptions: UnsafeHardhatRuntimeEnvironmentOptions = {}, +): Promise { + return createHardhatRuntimeEnvironment( + { ...config, plugins: [mockArtifactsPlugin, ...(config.plugins ?? [])] }, + userProvidedGlobalOptions, + projectRoot, + unsafeOptions, + ); +} + +const mockArtifactsPlugin: HardhatPlugin = { + id: "mock-artifacts", + dependencies: [async () => artifacts], + hookHandlers: { + hre: async () => { + return { + created: async (_context, hre): Promise => { + hre.artifacts = new MockArtifactsManager(); + }, + }; + }, + }, +}; diff --git a/v-next/hardhat/test/test-helpers/mock-artifacts-manager.ts b/v-next/hardhat/test/test-helpers/mock-artifacts-manager.ts new file mode 100644 index 0000000000..46f406416c --- /dev/null +++ b/v-next/hardhat/test/test-helpers/mock-artifacts-manager.ts @@ -0,0 +1,104 @@ +import type { + ArtifactsManager, + Artifact, + BuildInfo, + CompilerInput, + CompilerOutput, +} from "../../src/types/artifacts.js"; + +import { HardhatError } from "@ignored/hardhat-vnext-errors"; + +export class MockArtifactsManager implements ArtifactsManager { + readonly #artifacts: Map; + + constructor() { + this.#artifacts = new Map(); + } + + public async readArtifact( + contractNameOrFullyQualifiedName: string, + ): Promise { + const artifact = this.#artifacts.get(contractNameOrFullyQualifiedName); + + if (artifact === undefined) { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: + "Unable to find the artifact during mock readArtifact " + + contractNameOrFullyQualifiedName, + }); + } + + return artifact; + } + + public artifactExists( + _contractNameOrFullyQualifiedName: string, + ): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public getAllFullyQualifiedNames(): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public getBuildInfo( + _fullyQualifiedName: string, + ): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public getArtifactPaths(): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public getDebugFilePaths(): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public getBuildInfoPaths(): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public async saveArtifact(artifact: Artifact): Promise { + this.#artifacts.set(artifact.contractName, artifact); + } + + public saveBuildInfo( + _solcVersion: string, + _solcLongVersion: string, + _input: CompilerInput, + _output: CompilerOutput, + ): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public formArtifactPathFromFullyQualifiedName( + _fullyQualifiedName: string, + ): string { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } + + public getArtifactPath( + _contractNameOrFullyQualifiedName: string, + ): Promise { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + message: "Not implemented in MockArtifactsManager", + }); + } +} From 78277c88a386ab046d075f4aeedaf0cd4b98091b Mon Sep 17 00:00:00 2001 From: John Kane Date: Mon, 16 Sep 2024 22:24:55 +0100 Subject: [PATCH 3/4] refactor: use an explicit not implemented error By making not implemented an explicit error, we can track it in the code base (which is hardher if we piggy back on another error type). --- v-next/hardhat-errors/src/descriptors.ts | 9 +++++ .../internal/artifacts/artifacts-manager.ts | 18 +++++----- .../test-helpers/mock-artifacts-manager.ts | 35 ++++++++++--------- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/v-next/hardhat-errors/src/descriptors.ts b/v-next/hardhat-errors/src/descriptors.ts index 29f8f9eed1..afac459ab9 100644 --- a/v-next/hardhat-errors/src/descriptors.ts +++ b/v-next/hardhat-errors/src/descriptors.ts @@ -206,6 +206,15 @@ Please add the property "type" with the value "module" in your package.json to e websiteTitle: "Invariant violation", websiteDescription: `An internal invariant was violated. This is probably caused by a programming error in Hardhat or in one of the used plugins. +Please [report it](https://github.com/nomiclabs/hardhat/issues/new) to help us improve Hardhat.`, + shouldBeReported: true, + }, + NOT_IMPLEMENTED_ERROR: { + number: 101, + messageTemplate: "Not implemented: {message}", + websiteTitle: "Not implemented", + websiteDescription: `A code path that has not been implemented was unexpectedly triggered. + Please [report it](https://github.com/nomiclabs/hardhat/issues/new) to help us improve Hardhat.`, shouldBeReported: true, }, diff --git a/v-next/hardhat/src/internal/artifacts/artifacts-manager.ts b/v-next/hardhat/src/internal/artifacts/artifacts-manager.ts index cc9ca83839..9a26741f1b 100644 --- a/v-next/hardhat/src/internal/artifacts/artifacts-manager.ts +++ b/v-next/hardhat/src/internal/artifacts/artifacts-manager.ts @@ -12,7 +12,7 @@ export class ArtifactsManagerImplementation implements ArtifactsManager { public readArtifact( _contractNameOrFullyQualifiedName: string, ): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in fake artifacts manager", }); } @@ -20,13 +20,13 @@ export class ArtifactsManagerImplementation implements ArtifactsManager { public artifactExists( _contractNameOrFullyQualifiedName: string, ): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in fake artifacts manager", }); } public getAllFullyQualifiedNames(): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in fake artifacts manager", }); } @@ -34,25 +34,25 @@ export class ArtifactsManagerImplementation implements ArtifactsManager { public getBuildInfo( _fullyQualifiedName: string, ): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in fake artifacts manager", }); } public getArtifactPaths(): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in fake artifacts manager", }); } public getBuildInfoPaths(): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in fake artifacts manager", }); } public saveArtifact(_artifact: Artifact): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in fake artifacts manager", }); } @@ -63,13 +63,13 @@ export class ArtifactsManagerImplementation implements ArtifactsManager { _input: CompilerInput, _output: CompilerOutput, ): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in fake artifacts manager", }); } public getArtifactPath(_fullyQualifiedName: string): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in fake artifacts manager", }); } diff --git a/v-next/hardhat/test/test-helpers/mock-artifacts-manager.ts b/v-next/hardhat/test/test-helpers/mock-artifacts-manager.ts index 46f406416c..dbdc36456b 100644 --- a/v-next/hardhat/test/test-helpers/mock-artifacts-manager.ts +++ b/v-next/hardhat/test/test-helpers/mock-artifacts-manager.ts @@ -6,7 +6,10 @@ import type { CompilerOutput, } from "../../src/types/artifacts.js"; -import { HardhatError } from "@ignored/hardhat-vnext-errors"; +import { + assertHardhatInvariant, + HardhatError, +} from "@ignored/hardhat-vnext-errors"; export class MockArtifactsManager implements ArtifactsManager { readonly #artifacts: Map; @@ -20,13 +23,11 @@ export class MockArtifactsManager implements ArtifactsManager { ): Promise { const artifact = this.#artifacts.get(contractNameOrFullyQualifiedName); - if (artifact === undefined) { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { - message: - "Unable to find the artifact during mock readArtifact " + - contractNameOrFullyQualifiedName, - }); - } + assertHardhatInvariant( + artifact !== undefined, + "Unable to find the artifact during mock readArtifact " + + contractNameOrFullyQualifiedName, + ); return artifact; } @@ -34,13 +35,13 @@ export class MockArtifactsManager implements ArtifactsManager { public artifactExists( _contractNameOrFullyQualifiedName: string, ): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in MockArtifactsManager", }); } public getAllFullyQualifiedNames(): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in MockArtifactsManager", }); } @@ -48,25 +49,25 @@ export class MockArtifactsManager implements ArtifactsManager { public getBuildInfo( _fullyQualifiedName: string, ): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in MockArtifactsManager", }); } public getArtifactPaths(): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in MockArtifactsManager", }); } public getDebugFilePaths(): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in MockArtifactsManager", }); } public getBuildInfoPaths(): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in MockArtifactsManager", }); } @@ -81,7 +82,7 @@ export class MockArtifactsManager implements ArtifactsManager { _input: CompilerInput, _output: CompilerOutput, ): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in MockArtifactsManager", }); } @@ -89,7 +90,7 @@ export class MockArtifactsManager implements ArtifactsManager { public formArtifactPathFromFullyQualifiedName( _fullyQualifiedName: string, ): string { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in MockArtifactsManager", }); } @@ -97,7 +98,7 @@ export class MockArtifactsManager implements ArtifactsManager { public getArtifactPath( _contractNameOrFullyQualifiedName: string, ): Promise { - throw new HardhatError(HardhatError.ERRORS.INTERNAL.ASSERTION_ERROR, { + throw new HardhatError(HardhatError.ERRORS.INTERNAL.NOT_IMPLEMENTED_ERROR, { message: "Not implemented in MockArtifactsManager", }); } From 9fc2bd0c4c010f4dd3da5231dd84535bbd199fa5 Mon Sep 17 00:00:00 2001 From: John Kane Date: Tue, 17 Sep 2024 10:27:36 +0100 Subject: [PATCH 4/4] refactor: load artifacts manager dep lazily Match the pattern used for the network manager loading. This is the only category of hook where we lazily load as it is loaded every time the HRE is setup. --- .../{ => builtin-plugins}/artifacts/artifacts-manager.ts | 2 +- .../artifacts/{hookHandlers => hook-handlers}/hre.ts | 6 ++++-- .../hardhat/src/internal/builtin-plugins/artifacts/index.ts | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) rename v-next/hardhat/src/internal/{ => builtin-plugins}/artifacts/artifacts-manager.ts (98%) rename v-next/hardhat/src/internal/builtin-plugins/artifacts/{hookHandlers => hook-handlers}/hre.ts (77%) diff --git a/v-next/hardhat/src/internal/artifacts/artifacts-manager.ts b/v-next/hardhat/src/internal/builtin-plugins/artifacts/artifacts-manager.ts similarity index 98% rename from v-next/hardhat/src/internal/artifacts/artifacts-manager.ts rename to v-next/hardhat/src/internal/builtin-plugins/artifacts/artifacts-manager.ts index 9a26741f1b..73ec2a9b9c 100644 --- a/v-next/hardhat/src/internal/artifacts/artifacts-manager.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/artifacts/artifacts-manager.ts @@ -4,7 +4,7 @@ import type { BuildInfo, CompilerInput, CompilerOutput, -} from "../../types/artifacts.js"; +} from "../../../types/artifacts.js"; import { HardhatError } from "@ignored/hardhat-vnext-errors"; diff --git a/v-next/hardhat/src/internal/builtin-plugins/artifacts/hookHandlers/hre.ts b/v-next/hardhat/src/internal/builtin-plugins/artifacts/hook-handlers/hre.ts similarity index 77% rename from v-next/hardhat/src/internal/builtin-plugins/artifacts/hookHandlers/hre.ts rename to v-next/hardhat/src/internal/builtin-plugins/artifacts/hook-handlers/hre.ts index 9ec240e303..6414d45af0 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/artifacts/hookHandlers/hre.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/artifacts/hook-handlers/hre.ts @@ -1,10 +1,12 @@ import type { HardhatRuntimeEnvironmentHooks } from "../../../../types/hooks.js"; -import { ArtifactsManagerImplementation } from "../../../artifacts/artifacts-manager.js"; - export default async (): Promise> => { const handlers: Partial = { created: async (_context, hre): Promise => { + const { ArtifactsManagerImplementation } = await import( + "../artifacts-manager.js" + ); + hre.artifacts = new ArtifactsManagerImplementation(); }, }; diff --git a/v-next/hardhat/src/internal/builtin-plugins/artifacts/index.ts b/v-next/hardhat/src/internal/builtin-plugins/artifacts/index.ts index 2b2b6d3ff0..ae02872753 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/artifacts/index.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/artifacts/index.ts @@ -4,7 +4,7 @@ import "./type-extensions.js"; const hardhatPlugin: HardhatPlugin = { id: "artifacts", hookHandlers: { - hre: import.meta.resolve("./hookHandlers/hre.js"), + hre: import.meta.resolve("./hook-handlers/hre.js"), }, };