Sign Ethereum Message with Ledger

1 Install Necessary Packages

To get started, please install the following essential libraries that enable the script to interact with the Ledger Hardware Wallet.

The following package.json includes the specific versions of the dependencies.

touch package.json 
{
  "name": "npm-test",
  "version": "1.0.0",
  "source": "index.js",
  "type": "module",
  "scripts": {
    "start": "node index.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@ledgerhq/hw-app-eth": "6.29.0",
    "@ledgerhq/hw-transport-node-hid": "^6.28.4",
    "ethers": "5.5.4"
  },
  "main": "index.js",
  "description": ""
}

By including this package.json in the project, run npm install to install all required dependencies at their specified versions.

npm install

After the required dependencies are installed, run npm list and the result should looks like the following example.

npm list
├── @ledgerhq/[email protected]
├── @ledgerhq/[email protected]
└── [email protected]

2 Create JavaScript Script

Create the Javascript script.

touch index.js

The following code is an example of signing Ethereum transaction with Ledger. This is revised from the Ledger official tech doc.

import { ethers } from "ethers";
import TransportNodeHid from "@ledgerhq/hw-transport-node-hid";
import Eth from "@ledgerhq/hw-app-eth";

// Connect to Ledger
const transport = await TransportNodeHid.default.create();
const eth = new Eth.default(transport);
const result = await eth.getAddress("44'/60'/0'/0/0")
console.log("Connected to Ledger \nWallet address is", result.address);

// Sign message
let message = {validators: ["<ethereum_validator_address_1>","<ethereum_validator_address_2>"]}
const signature = await eth.signPersonalMessage("44'/60'/0'/0/0", Buffer.from(JSON.stringify(message)).toString("hex"));
const signedHash = "0x" + signature.r + signature.s + signature.v.toString(16);
console.log("Signature is", signedHash);

3 Connect Ledger Hardware Wallet

Refer to Ledger Developer Portal about how to "Plug Your Ledger Device".

4 Execute Script

node index.js

During the script is running, it retrieves Ledger wallet address and display as the following format:

Connected to Ledger 
Wallet address is <your-etheruem-wallet-address>

Ledger will display the details of the transaction to be signed, press the button to approve all the messages. The signature will be displayed as the following format

Signature is <signature>

5 Use Signature to Unstake or Claim Reward

The generated signature could be used to unstake ETH or claim reward via InfStones Staking API.