npm package: @l8d/hardhat-ledger
Description: Hardhat v3 plugin for the Ledger hardware wallet
Author: Nomic Foundation
Latest version: 1.0.0

[![npm](https://img.shields.io/npm/v/@nomicfoundation/hardhat-ledger.svg)](https://www.npmjs.com/package/@nomicfoundation/hardhat-ledger) [![hardhat](https://hardhat.org/buidler-plugin-badge.svg?1)](https://hardhat.org)

# hardhat-ledger

[Hardhat](https://hardhat.org) plugin for integration with a [Ledger hardware wallet](https://www.ledger.com/).

## What

This plugin extends the Hardhat network connection to work with a connected Ledger wallet seamlessly.

## Installation

**For Hardhat v3:**

```bash
npm install --save-dev @nomicfoundation/hardhat-ledger
```

Import and add the plugin to your `hardhat.config.ts`:

```typescript
import { defineConfig } from "hardhat/config";
import hardhatLedger from "@nomicfoundation/hardhat-ledger";

export default defineConfig({
  plugins: [hardhatLedger],
  // ... rest of config
});
```

Or in JavaScript (`hardhat.config.js`):

```javascript
import { defineConfig } from "hardhat/config";
import hardhatLedger from "@nomicfoundation/hardhat-ledger";

export default defineConfig({
  plugins: [hardhatLedger],
  // ... rest of config
});
```

**For Hardhat v2:**

```bash
npm install --save-dev @nomicfoundation/hardhat-ledger@1
```

And add the following to your `hardhat.config.js`:

```js
require("@nomicfoundation/hardhat-ledger");
```

Or for TypeScript (`hardhat.config.ts`):

```js
import "@nomicfoundation/hardhat-ledger";
```

## Tasks

This plugin creates no additional tasks.

## Environment extensions

This plugin adds nothing to the Hardhat Runtime Environment.

## How it works

In Hardhat v3, this plugin uses the network hooks system to wrap the provider with a `LedgerProvider` when you create a network connection. The `LedgerProvider` knows how to connect and interact with a Ledger wallet.

In Hardhat v2, the plugin used `extendProvider` to decorate the provider.

## Usage

Configure the plugin through the Hardhat Config by adding `ledgerAccounts` to your network configuration.

**For Hardhat v3** (`hardhat.config.ts`):

```typescript
import { defineConfig } from "hardhat/config";
import hardhatLedger from "@nomicfoundation/hardhat-ledger";

export default defineConfig({
  plugins: [hardhatLedger],
  networks: {
    sepolia: {
      url: "https://sepolia.infura.io/v3/YOUR-PROJECT-ID",
      ledgerAccounts: [
        "0xa809931e3b38059adae9bc5455bc567d0509ab92",
        "0xda6a52afdae5ff66aa786da68754a227331f56e3",
        "0xbc307688a80ec5ed0edc1279c44c1b34f7746bda",
      ],
    },
  },
});
```

**For Hardhat v2** (`hardhat.config.js`):

```js
require("@nomicfoundation/hardhat-ledger");

module.exports = {
  networks: {
    sepolia: {
      url: "https://sepolia.infura.io/v3/YOUR-PROJECT-ID",
      ledgerAccounts: [
        "0xa809931e3b38059adae9bc5455bc567d0509ab92",
        "0xda6a52afdae5ff66aa786da68754a227331f56e3",
        "0xbc307688a80ec5ed0edc1279c44c1b34f7746bda",
      ],
    },
  },
};
```

This will make those three accounts available to the `LedgerProvider`. If you try to send a transaction or sign something using any of those accounts, the provider will try to connect to the Ledger wallet and find a derivation path for that address. By default, the derivation paths that are tried start from `m/44'/60'/0'/0'/0` and go way up to `m/44'/60'/20'/0'/0`.

An additional (optional) configuration is possible to specify the derivation path that should be used, allowing 'legacy' or otherwise non-standard addresses to still be used with the plugin. You can also configure connection timeouts. An example:

**Hardhat v3:**

```typescript
export default defineConfig({
  networks: {
    sepolia: {
      url: "https://sepolia.infura.io/v3/YOUR-PROJECT-ID",
      ledgerAccounts: [
        "0xa809931e3b38059adae9bc5455bc567d0509ab92",
      ],
      ledgerOptions: {
        derivationFunction: (x) => `m/44'/60'/0'/${x}`, // legacy derivation path
        openTimeout: 5000, // ms to wait for ledger to open
        connectionTimeout: 5000, // ms to wait for connection
      },
    },
  },
});
```

**Hardhat v2:**

```js
module.exports = {
  networks: {
    sepolia: {
      url: "https://sepolia.infura.io/v3/YOUR-PROJECT-ID",
      ledgerAccounts: [...],
      ledgerOptions: {
        derivationFunction: (x) => `m/44'/60'/0'/${x}` // legacy derivation path
      }
    }
  }
};
```

### Using with Scripts and Tasks

**Hardhat v3:**

```typescript
import { task } from "hardhat/config";

task("sign", "Signs a message").setAction(async (_, hre) => {
  const message =
    "0x5417aa2a18a44da0675524453ff108c545382f0d7e26605c56bba47c21b5e979";
  const account = "0xa809931e3b38059adae9bc5455bc567d0509ab92";

  // Connect to the network
  const connection = await hre.network.connect("sepolia");

  const signature = await connection.provider.request({
    method: "personal_sign",
    params: [message, account],
  });

  console.log(
    "Signed message",
    message,
    "for Ledger account",
    account,
    "and got",
    signature
  );
});
```

**Hardhat v2:**

```js
task("sign", "Signs a message", async (_, hre) => {
  const message =
    "0x5417aa2a18a44da0675524453ff108c545382f0d7e26605c56bba47c21b5e979";
  const account = "0xa809931e3b38059adae9bc5455bc567d0509ab92";

  const signature = await hre.network.provider.request({
    method: "personal_sign",
    params: [message, account],
  });

  console.log(
    "Signed message",
    message,
    "for Ledger account",
    account,
    "and got",
    signature
  );
});
```

## Debugging

This plugin uses the [`debug`](https://www.npmjs.com/package/debug) package for logging. By default, all debug output is hidden. To enable it, set the `DEBUG` environment variable:

```bash
# Enable all hardhat-ledger debug logs
DEBUG=hardhat-ledger:* npx hardhat run script.js

# Enable only provider logs
DEBUG=hardhat-ledger:provider npx hardhat run script.js

# Enable only network hook logs
DEBUG=hardhat-ledger:network npx hardhat run script.js

# Enable all debug logs (including other packages)
DEBUG=* npx hardhat run script.js
```

Available debug namespaces:
- `hardhat-ledger:provider` - Provider operations and transaction signing
- `hardhat-ledger:network` - Network connection and configuration
- `hardhat-ledger:create` - LedgerProvider instantiation

## Errors

The package throws and exports a few [errors](https://github.com/NomicFoundation/hardhat/blob/main/packages/hardhat-core/src/config.ts). In case you ever need to catch and check for them, you can use the `public static` method present on each of them. For example:

```ts
try {
  //(...)
} catch (error) {
  if (DerivationPathError.isDerivationPathError(error)) {
    // error is a DerivationPathError
  }
}
```

Same for the other errors, all have their corresponding `.isXXXError()` method.