Skip to Content
📢 Breaking change: Applications using LedgerJS for transport implementation should migrate to the Device Management Kit (DMK). Learn more.

Read accounts and sign a transaction

In this tutorial, we will read accounts from the Wallet API and sign one Ethereum transaction. By the end, App.tsx will list the accounts and show a signature response.

This page continues Configure the Wallet API.

6. Read accounts

Create src/hooks/useAccounts.tsx. The useAccounts hook from @ledgerhq/wallet-api-client-react returns the accounts, a loading flag, and an error.

// src/hooks/useAccounts.tsx import { useAccounts } from "@ledgerhq/wallet-api-client-react"; function useUserAccounts() { const { accounts, loading, error } = useAccounts(); return { accounts, loading, error, }; } export default useUserAccounts;

We can call useUserAccounts from a component. The list is empty until the transport is connected.

7. Sign an Ethereum transaction

Create src/hooks/useSignTransaction.tsx. useRequestAccount selects an account. useSignTransaction asks the signer to sign the transaction we pass in.

// src/hooks/useSignTransaction.tsx import { useSignTransaction, useRequestAccount, } from "@ledgerhq/wallet-api-client-react"; import { useCallback, useState, useEffect } from "react"; import BigNumber from "bignumber.js"; function useTransactionSigner() { const { requestAccount, account } = useRequestAccount(); const { signTransaction, pending, signature, error } = useSignTransaction(); const [response, setResponse] = useState(null); useEffect(() => { requestAccount(); }, [requestAccount]); const handleSignTransaction = useCallback(async () => { if (!account) return; const ethereumTransaction = { family: "ethereum", amount: new BigNumber(1000000000000000), // 0.001 ETH in wei recipient: "0xRecipientAddressHere", gasPrice: new BigNumber(20000000000), // 20 Gwei gasLimit: new BigNumber(21000), nonce: 0, // Replace with the correct nonce }; try { const signature = await signTransaction(account.id, ethereumTransaction); setResponse(signature); } catch (e) { console.error(e); } }, [account, signTransaction]); return { handleSignTransaction, pending, response, error, }; } export default useTransactionSigner;

8. Show the accounts and the signature

Create src/App.tsx. It renders the accounts from useUserAccounts and a button that calls handleSignTransaction.

// src/App.tsx import React from "react"; import useUserAccounts from "./hooks/useAccounts"; import useTransactionSigner from "./hooks/useSignTransaction"; function App() { const { accounts, loading, error } = useUserAccounts(); const { handleSignTransaction, pending, response, error: signError, } = useTransactionSigner(); return ( <> <h1>User's Crypto Accounts</h1> {loading ? ( <p>Loading...</p> ) : error ? ( <p>Error: {error.message}</p> ) : ( <ul> {(accounts ?? []).map(({ id, name, address, currency, balance }) => ( <li key={id}> <p>id: {id}</p> <p>name: {name}</p> <p>address: {address}</p> <p>currency: {currency}</p> {/* Make sure to parse BigNumber */} <p>balance: {balance.toString()}</p> </li> ))} </ul> )} <button onClick={handleSignTransaction} disabled={pending}> Sign Ethereum Transaction </button> {pending && <p>Signing...</p>} {signError && <p>Error: {signError.toString()}</p>} {response && ( <p>Transaction signed successfully: {response.toString("hex")}</p> )} </> ); } export default App;

We have an app that lists accounts and requests one signature. The recipient in the sample is still 0xRecipientAddressHere, and the nonce is 0. We replace both before a signature can be accepted. Next: Load the manifest.

Last updated on
Ledger
Copyright © Ledger SAS. All rights reserved. Ledger, Ledger Stax, Ledger Flex, Ledger Nano, Ledger Nano S, Ledger OS, Ledger Wallet, [LEDGER] (logo), [L] (logo) are trademarks owned by Ledger SAS.