---
title: Write a plugin for Clear Signing
category: how-to
---

# Write a plugin for Clear Signing

This page shows how to add a Ledger plugin to a dApp running in the Ledger Wallet dApp browser, so transactions on your contracts display human-readable details on the device instead of raw hex.

A Ledger plugin is a small C application installed alongside the [Ethereum device app](../../../../device-app/explanation/plugin/). When the user signs a transaction whose `to` address matches one of your plugin's registered contracts, the Ethereum app delegates the on-screen rendering to your plugin via a defined handler interface (`handle_init_contract`, `handle_provide_parameter`, `handle_finalize`, and others). Source: [`LedgerHQ/app-plugin-boilerplate`](https://github.com/LedgerHQ/app-plugin-boilerplate) and [`LedgerHQ/ethereum-plugin-sdk`](https://github.com/LedgerHQ/ethereum-plugin-sdk).

> **Note:** Before starting, check whether [ERC-7730](../../../clear-signing/overview) covers your contracts. ERC-7730 is metadata-only, requires no on-device code, and is the supported path for most use cases. Plugins are reserved for contracts whose data does not fit the ERC-7730 schema.

> **Warning:** Plugin development requires Ledger's prior approval. If your dApp does not already have a plugin slot agreed with Ledger, [request one](../../../../device-app/integration/how-to/plugin) before following this guide.

## Prerequisites

- Ledger has approved a plugin slot for your dApp.
- You have built a working plugin from [`app-plugin-boilerplate`](https://github.com/LedgerHQ/app-plugin-boilerplate) using the [Ethereum Plugin SDK](https://ethereum-plugin-sdk.ledger.com/), and your plugin passes the boilerplate's functional tests.
- Your Live App already loads in Ledger Wallet via a manifest. If not, start with [Write and load the manifest](./manifest).

## Steps

### 1. Build and submit your plugin

Follow the device-app guide [How to develop an Ethereum plugin](../../../../device-app/integration/how-to/plugin) for the full development flow:

1. Fork [`app-plugin-boilerplate`](https://github.com/LedgerHQ/app-plugin-boilerplate) and implement the SDK handlers for your contracts.
2. Add functional tests covering every transaction path your plugin parses. They are mandatory for submission.
3. Submit your plugin to Ledger's [submission process](../../../../device-app/submission-process/process). The plugin name you ship with is the value you will reference from the manifest in the next step.

### 2. Reference the plugin in your dApp manifest

Once Ledger has accepted your plugin, set its **exact name** as `dapp.nanoApp` in your [manifest](./manifest):

```json
{
  "id": "your-dapp-id",
  "name": "Your dApp",
  "url": "https://yourdapp.example",
  "dapp": {
    "nanoApp": "YourPluginName",
    "networks": [
      {
        "currency": "ethereum",
        "chainID": 1,
        "nodeURL": "https://eth-dapps.api.live.ledger.com"
      }
    ]
  },
  "manifestVersion": "2",
  "apiVersion": "^2.0.0",
  "branch": "stable"
}
```

The `nanoApp` value must match the plugin name registered with Ledger character-for-character (capitalization included). Use `"Ethereum"` only if your dApp does not require a plugin.

See the [manifest reference](./manifest) for the full list of fields and an end-to-end example.

### 3. Test the integration end-to-end

1. Enable [Developer mode](../../references/developer-mode/) in Ledger Wallet.
2. Install the latest Ethereum app and your plugin on the device.
3. [Add your local app](../../references/developer-mode#add-a-local-app) using the manifest from step 2.
4. Sign a transaction on each contract path your plugin handles and confirm the device shows the expected fields.

If a transaction still displays raw hex, see [Common pitfalls](#common-pitfalls).

## Common pitfalls

- **Plugin not invoked.** The Ethereum app only delegates to a plugin when the recipient address is in the plugin's registered contract list. Double-check the `to` of the transaction matches one of the contracts declared in your plugin.
- **`nanoApp` name mismatch.** A typo or wrong case in `dapp.nanoApp` falls back silently to blind signing. Copy the name from the plugin repository's `Makefile`.
- **Wrong network.** A plugin only loads when the chain matches one of the entries in `dapp.networks`. Add the chain you are testing on (Ledger Wallet currently supports mainnet, BSC, Arbitrum, Optimism, Base, Fantom, and Polygon).
- **Old Ethereum app.** Plugins are pinned to a minimum Ethereum app version. Update the Ethereum app on the device if the plugin fails to load.
- **CI guidelines failing.** The `Guidelines_enforcer` workflow on the boilerplate runs Ledger's app guidelines; fix every reported rule before submitting (see [device-app development requirements](../../../../device-app/integration/requirements/development)).

## See also

- [How to develop an Ethereum plugin](../../../../device-app/integration/how-to/plugin): full plugin development flow and submission process.
- [Ethereum Plugin SDK](https://ethereum-plugin-sdk.ledger.com/): handler reference and architecture.
- [`app-plugin-boilerplate`](https://github.com/LedgerHQ/app-plugin-boilerplate): forkable starting point.
- [Clear signing with ERC-7730](../../../clear-signing/overview): the metadata-only alternative for simpler contracts.
