Sign Ethereum Transaction with Ledger
1 Install Necessary Packages
To get started, please install the following essential libraries that enable the script to interact with the Ethereum blockchain and 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",
"web3": "4.5.0"
},
"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]
└── [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";
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);
import Web3 from "web3";
const web3 = new Web3("<ethereum_endpoint>"); // Replace this with your Ethereum Fast API endpoint
const txCount = await web3.eth.getTransactionCount(result.address);
const nonce = await web3.utils.toHex(txCount)
const gasPrice = await web3.eth.getGasPrice();
const chainId = await web3.eth.getChainId();
// The transaction to be signed
let rawTx = {
nonce: nonce,
to: '0x3070eb0eac184cb84e825dfff97070521424accd', // This is InfStones Ethereum Staking Smart Contract Address
gasPrice: web3.utils.toHex(gasPrice),
data: "<data>", //retrieved from activity
value: "<value>", //retrieved from activity
chainId: Number(chainId), // mainnet: 1, goerli: 5
}
const estimateGas = await web3.eth.estimateGas(rawTx)
rawTx = { ...rawTx, gasLimit: estimateGas}
//Serializing the transaction to pass it to Ledger Nano for signing
let unsignedTx = ethers.utils.serializeTransaction(rawTx).substring(2);
//Sign with the Ledger Nano (Sign what you see)
const signature = await eth.signTransaction("44'/60'/0'/0/0", unsignedTx, null);
signature.r = "0x" + signature.r;
signature.s = "0x" + signature.s;
signature.v = parseInt(signature.v);
signature.from = result.address;
//Serialize the same transaction as before, but adding the signature on it
let signedTx = ethers.utils.serializeTransaction(rawTx, signature);
console.log("Signature is ", signedTx);
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 Send Transaction
Copy the signature
from the last step, paste it to the following request.
Complete the stake process by sending the signed transaction anytime.
curl --location 'http://<ethereum_endpoint>' \
--header 'Content-Type: application/json' \
--data '{
"jsonrpc": "2.0",
"method": "eth_sendRawTransaction",
"params": [
"<signature_from_above_script>"
],
"id": 1
}'
Updated 7 months ago