or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

artifact-management.mdconfiguration.mdhook-system.mdindex.mdnetwork-management.mdplugin-system.mdsolidity-build-system.mdtask-management.mdutilities.md
tile.json

plugin-system.mddocs/

Plugin System

Hardhat's plugin system provides a modular architecture for extending functionality through plugins with dependency management, lifecycle hooks, and type-safe extensions.

Capabilities

Plugin Definition

Core interface for defining Hardhat plugins with metadata and functionality.

interface HardhatPlugin {
  /** Unique plugin identifier */
  id: string;
  
  /** NPM package name containing the plugin */
  npmPackage: string;
  
  /** Hook handlers provided by the plugin */
  hookHandlers?: Partial<HardhatPluginHookHandlers>;
  
  /** Global CLI options added by the plugin */
  globalOptions?: GlobalOptionDefinition[];
  
  /** Plugin dependencies (lazy-loaded) */
  dependencies?: () => Promise<HardhatPlugin>[];
  
  /** Plugin initialization function */
  init?: (hre: HardhatRuntimeEnvironment) => Promise<void>;
}

Usage Examples:

import type { HardhatPlugin } from "hardhat/types";

const myPlugin: HardhatPlugin = {
  id: "my-custom-plugin",
  npmPackage: "hardhat-my-plugin",
  hookHandlers: {
    hre: () => import("./hre-hooks.js"),
    config: () => import("./config-hooks.js")
  },
  globalOptions: [
    {
      name: "my-option",
      description: "Custom plugin option",
      type: ArgumentType.STRING,
      defaultValue: "default"
    }
  ],
  dependencies: () => [
    import("hardhat-dependency-plugin")
  ],
  init: async (hre) => {
    // Plugin initialization logic
    console.log(`Initializing plugin on network: ${hre.network.name}`);
  }
};

export default myPlugin;

Plugin Hook Handlers

Hook handler definitions that plugins can implement.

interface HardhatPluginHookHandlers {
  /** Configuration-related hook handlers */
  config?: () => Promise<ConfigHookHandlers>;
  
  /** HRE lifecycle hook handlers */
  hre?: () => Promise<HreHookHandlers>;
  
  /** Configuration variable hook handlers */
  configurationVariables?: () => Promise<ConfigVarHookHandlers>;
  
  /** User interruption hook handlers */
  userInterruptions?: () => Promise<UserInterruptionHookHandlers>;
}

interface ConfigHookHandlers {
  resolveUserConfig?: (
    userConfig: HardhatUserConfig,
    context: ConfigHookContext
  ) => Promise<HardhatUserConfig>;
  
  configResolved?: (
    config: HardhatConfig,
    context: ConfigHookContext
  ) => Promise<void>;
  
  validateConfig?: (
    config: HardhatConfig,
    context: ConfigHookContext
  ) => Promise<void>;
}

interface HreHookHandlers {
  initialized?: (
    hre: HardhatRuntimeEnvironment,
    context: HookContext
  ) => Promise<void>;
  
  beforeTaskRun?: (
    taskName: string,
    taskArguments: TaskArguments,
    context: HookContext
  ) => Promise<void>;
  
  afterTaskRun?: (
    taskName: string,
    taskArguments: TaskArguments,
    result: any,
    context: HookContext
  ) => Promise<void>;
  
  taskFailed?: (
    taskName: string,
    taskArguments: TaskArguments,
    error: Error,
    context: HookContext
  ) => Promise<void>;
}

Global Options

Plugin-defined global CLI options that extend Hardhat's command-line interface.

interface GlobalOptionDefinition {
  /** Option name (without dashes) */
  name: string;
  
  /** Option description for help text */
  description: string;
  
  /** Argument type */
  type: ArgumentType;
  
  /** Default value */
  defaultValue?: ArgumentTypeToValueType[ArgumentType];
  
  /** Short flag name */
  shortName?: string;
  
  /** Whether the option is a flag (boolean) */
  isFlag?: boolean;
  
  /** Whether the option is required */
  isRequired?: boolean;
}

/**
 * Creates a global option definition
 * @param definition - The option definition
 */
function globalOption(definition: GlobalOptionDefinition): void;

Usage Examples:

import { globalOption, ArgumentType } from "hardhat/config";

// Add a string option
globalOption({
  name: "api-key",
  description: "API key for external service",
  type: ArgumentType.STRING,
  defaultValue: undefined
});

// Add a boolean flag
globalOption({
  name: "verbose-logging",
  description: "Enable verbose logging",
  type: ArgumentType.BOOLEAN,
  defaultValue: false,
  isFlag: true
});

// Add a number option with short name
globalOption({
  name: "max-retries",
  shortName: "r",
  description: "Maximum number of retries",
  type: ArgumentType.INT,
  defaultValue: 3
});

Plugin Dependencies

System for managing plugin dependencies and load order.

type PluginDependency = 
  | string 
  | { name: string; optional?: boolean }
  | (() => Promise<HardhatPlugin>);

interface PluginDependencyInfo {
  /** Plugin name or identifier */
  name: string;
  
  /** Whether the dependency is optional */
  optional: boolean;
  
  /** Resolved plugin instance */
  plugin?: HardhatPlugin;
  
  /** Load status */
  status: "pending" | "loading" | "loaded" | "failed";
  
  /** Load error if failed */
  error?: Error;
}

Plugin Registry

System for registering and managing plugins.

interface PluginRegistry {
  /** Register a plugin */
  register(plugin: HardhatPlugin): void;
  
  /** Get a registered plugin by ID */
  get(pluginId: string): HardhatPlugin | undefined;
  
  /** Check if a plugin is registered */
  has(pluginId: string): boolean;
  
  /** Get all registered plugin IDs */
  getPluginIds(): string[];
  
  /** Load and initialize all plugins */
  loadAll(hre: HardhatRuntimeEnvironment): Promise<void>;
  
  /** Get plugin dependency graph */
  getDependencyGraph(): Map<string, string[]>;
}

Plugin Error Handling

Specialized error handling for plugin-related issues.

class HardhatPluginError extends Error {
  /** Plugin name that caused the error */
  readonly pluginName: string;
  
  /** Original error if this wraps another error */
  readonly parent?: Error;
  
  constructor(
    pluginName: string,
    message: string,
    parent?: Error
  );
}

interface PluginLoadError extends Error {
  /** Plugin ID that failed to load */
  pluginId: string;
  
  /** Type of load error */
  errorType: "missing" | "invalid" | "dependency" | "initialization";
  
  /** Additional error context */
  context?: any;
}

Usage Examples:

import { HardhatPluginError } from "hardhat/plugins";

// In plugin code, throw plugin-specific errors
throw new HardhatPluginError(
  "my-plugin",
  "Failed to connect to external service",
  originalError
);

// Handle plugin errors
try {
  await hre.run("my-plugin-task");
} catch (error) {
  if (error instanceof HardhatPluginError) {
    console.log(`Plugin error in ${error.pluginName}: ${error.message}`);
  }
}

Type Extensions

Plugins can extend Hardhat's type system through module augmentation.

Usage Examples:

// In plugin's type extension file
declare module "hardhat/types/hre" {
  interface HardhatRuntimeEnvironment {
    myPlugin: {
      doSomething(): Promise<void>;
      getSomething(): string;
    };
  }
}

declare module "hardhat/types/config" {
  interface HardhatUserConfig {
    myPlugin?: {
      enabled?: boolean;
      apiKey?: string;
    };
  }
  
  interface HardhatConfig {
    myPlugin: {
      enabled: boolean;
      apiKey?: string;
    };
  }
}

// In plugin implementation
export async function initialized(hre, context) {
  hre.myPlugin = {
    doSomething: async () => {
      console.log("Doing something...");
    },
    getSomething: () => "something"
  };
}

Plugin Lifecycle

Plugins follow a specific lifecycle during loading and execution.

interface PluginLifecycle {
  /** Phase 1: Plugin registration */
  register: () => void;
  
  /** Phase 2: Dependency resolution */
  resolveDependencies: () => Promise<void>;
  
  /** Phase 3: Plugin initialization */
  initialize: (hre: HardhatRuntimeEnvironment) => Promise<void>;
  
  /** Phase 4: Hook handler registration */
  registerHooks: (hre: HardhatRuntimeEnvironment) => Promise<void>;
  
  /** Phase 5: Plugin ready for use */
  ready: () => void;
}