DocumentationDevice interactionReferencesSignersSigner Ethereum (EVM)

Ethereum Signer Kit

Features

Following doc is matching for v1.0.0 of the Ethereum Signer Kit.

1: Get Address

This method allows users to retrieve the Ethereum address according to given derivationPath.

const { observable, cancel } = signerEth.getAddress(derivationPath, options);

Parameters

  • derivationPath

    • Required
    • Type: string (e.g., "44'/60'/0'/0/0")
    • The derivation path used for the Ethereum address. See here for more information.
  • options

    • Optional

    • Type: AddressOptions

      type AddressOptions = {
        checkOnDevice?: boolean;
        returnChainCode?: boolean;
      };
    • checkOnDevice: An optional boolean indicating whether user confirmation on the device is required (true) or not (false).

    • returnChainCode: An optional boolean indicating whether the chain code should be returned (true) or not (false).

Returns

  • observable

    • An Observable object that contains the DeviceActionState derived instance, which reprensents the operation’s state. For example:

      observable.subscribe({
        next: (state: DeviceActionState) => {
          switch (state.status) {
            case DeviceActionStatus.NotStarted: {
              console.log("The action is not started yet.");
              break;
            }
            case DeviceActionStatus.Pending: {
              const {
                intermediateValue: { requiredUserInteraction },
              } = state;
              // Access the intermediate value here, explained below
              console.log(
                "The action is pending and the intermediate value is: ",
                intermediateValue,
              );
              break;
            }
            case DeviceActionStatus.Stopped: {
              console.log("The action has been stopped.");
              break;
            }
            case DeviceActionStatus.Completed: {
              const { output } = state;
              // Access the output of the completed action here
              console.log("The action has been completed: ", output);
              break;
            }
            case DeviceActionStatus.Error: {
              const { error } = state;
              // Access the error here if occured
              console.log("An error occured during the action: ", error);
              break;
            }
          }
        },
      });
    • When the action status is DeviceActionStatus.Pending, the state will include an intermediateValue object that provides useful information for interaction:

      const { requiredUserInteraction } = intermediateValue;
       
      switch (requiredUserInteraction) {
        case UserInteractionRequired.VerifyAddress: {
          // User needs to verify the address displayed on the device
          console.log(
            "User needs to verify the address displayed on the device.",
          );
          break;
        }
        case UserInteractionRequired.None: {
          // No user action required
          console.log("No user action needed.");
          break;
        }
        case UserInteractionRequired.UnlockDevice: {
          // User needs to unlock the device
          console.log("The user needs to unlock the device.");
          break;
        }
        case UserInteractionRequired.ConfirmOpenApp: {
          // User needs to confirm on the device to open the app
          console.log("The user needs to confirm on the device to open the app.");
          break;
        }
        default:
          // Type guard to ensure all cases are handled
          const uncaughtUserInteraction: never = requiredUserInteraction;
          console.error(
            "Unhandled user interaction case:",
            uncaughtUserInteraction,
          );
      }
    • When the action status is DeviceActionStatus.Completed, the execution result can be accessed through the output property in the state. The output property is of type GetAddressCommandResponse, which has the following structure:

      type GetAddressCommandResponse = {
        publicKey: string;
        address: `0x${string}`;
        chainCode?: string;
      };
  • cancel

    • The function without a return value to cancel the action on the Ledger device.

2: Sign Transaction

This method enables users to securely sign transactions using clear signing on Ledger devices.

const { observable, cancel } = signerEth.signTransaction(
  derivationPath,
  transaction,
  options,
);

Parameters

  • derivationPath

    • Required
    • Type: string (e.g., "44'/60'/0'/0/0")
    • The derivation path used in the transaction. See here for more information.
  • transaction

    • Required
    • Type:Transaction (compatible with ethers v5 or ethers v6)
    • The transaction object that needs to be signed.
  • options

    • Optional

    • Type: TransactionOptions

      type TransactionOptions = {
        domain?: string;
      };
    • domain An optional string representing the domain present in the transaction. Currently, only ENS domains are supported.

Returns

  • observable

    • An Observable object that contains the DeviceActionState derived instance which reprensents the operation’s state. For example:

      observable.subscribe({
        next: (state: SignTransactionDAState) => {
          switch (state.status) {
            case DeviceActionStatus.NotStarted: {
              console.log("The action is not started yet.");
              break;
            }
            case DeviceActionStatus.Pending: {
              const {
                intermediateValue: { requiredUserInteraction },
              } = state;
              // Access the intermediate value here, explained below
              console.log(
                "The action is pending and the intermediate value is: ",
                intermediateValue,
              );
              break;
            }
            case DeviceActionStatus.Stopped: {
              console.log("The action has been stopped.");
              break;
            }
            case DeviceActionStatus.Completed: {
              const { output } = state;
              // Access the output of the completed action here
              console.log("The action has been completed: ", output);
              break;
            }
            case DeviceActionStatus.Error: {
              const { error } = state;
              // Access the error here if occured
              console.log("An error occured during the action: ", error);
              break;
            }
          }
        },
      });
    • When the action status is DeviceActionStatus.Pending, the state will include an intermediateValue object that provides useful information for interaction:

      const { requiredUserInteraction } = intermediateValue;
       
      switch (requiredUserInteraction) {
        case UserInteractionRequired.SignTransaction: {
          // User needs to sign the transaction displayed on the device
          console.log(
            "User needs to sign the transaction displayed on the device.",
          );
          break;
        }
        case UserInteractionRequired.None: {
          // No user action required
          console.log("No user action needed.");
          break;
        }
        case UserInteractionRequired.UnlockDevice: {
          // User needs to unlock the device
          console.log("The user needs to unlock the device.");
          break;
        }
        case UserInteractionRequired.ConfirmOpenApp: {
          // User needs to confirm on the device to open the app
          console.log("The user needs to confirm on the device to open the app.");
          break;
        }
        default:
          // Type guard to ensure all cases are handled
          const uncaughtUserInteraction: never = requiredUserInteraction;
          console.error(
            "Unhandled user interaction case:",
            uncaughtUserInteraction,
          );
      }
    • When the action status is DeviceActionStatus.Completed, the execution result can be accessed through the output property in the state. This property is a Signature object with the following structure:

      type Signature = {
        r: `0x${string}`;
        s: `0x${string}`;
        v: number;
      };
  • cancel

    • The function without a return value to cancel the action on the Ledger device.

3: Sign Message

This method allows users to sign a text string that is displayed on Ledger devices.

const { observable, cancel } = signerEth.signMessage(derivationPath, message);

Parameters

  • derivationPath

    • Required
    • Type: string (e.g., "44'/60'/0'/0/0")
    • The derivation path used by the Ethereum message. See here for more information.
  • message

    • Required
    • Type: string
    • The message to be signed, which will be displayed on the Ledger device.

Returns

  • observable

    • An Observable object that contains the DeviceActionState derived instance which reprensents the operation’s state. For example:

      observable.subscribe({
        next: (state: SignPersonalMessageDAState) => {
          switch (state.status) {
            case DeviceActionStatus.NotStarted: {
              console.log("The action is not started yet.");
              break;
            }
            case DeviceActionStatus.Pending: {
              const {
                intermediateValue: { requiredUserInteraction },
              } = state;
              // Access the intermediate value here, explained below
              console.log(
                "The action is pending and the intermediate value is: ",
                intermediateValue,
              );
              break;
            }
            case DeviceActionStatus.Stopped: {
              console.log("The action has been stopped.");
              break;
            }
            case DeviceActionStatus.Completed: {
              const { output } = state;
              // Access the output of the completed action here
              console.log("The action has been completed: ", output);
              break;
            }
            case DeviceActionStatus.Error: {
              const { error } = state;
              // Access the error here if occured
              console.log("An error occured during the action: ", error);
              break;
            }
          }
        },
      });
    • When the action status is DeviceActionStatus.Pending, the state will include an intermediateValue object that provides useful information for interaction:

      const { requiredUserInteraction } = intermediateValue;
       
      switch (requiredUserInteraction) {
        case UserInteractionRequired.SignPersonalMessage: {
          // User needs to sign the message displayed on the device
          console.log("User needs to sign the message displayed on the device.");
          break;
        }
        case UserInteractionRequired.None: {
          // No user action required
          console.log("No user action needed.");
          break;
        }
        case UserInteractionRequired.UnlockDevice: {
          // User needs to unlock the device
          console.log("The user needs to unlock the device.");
          break;
        }
        case UserInteractionRequired.ConfirmOpenApp: {
          // User needs to confirm on the device to open the app
          console.log("The user needs to confirm on the device to open the app.");
          break;
        }
        default:
          // Type guard to ensure all cases are handled
          const uncaughtUserInteraction: never = requiredUserInteraction;
          console.error(
            "Unhandled user interaction case:",
            uncaughtUserInteraction,
          );
      }
    • When the action status is DeviceActionStatus.Completed, the execution result can be accessed through the output property in the state. This property is a Signature object with the following structure:

      type Signature = {
        r: `0x${string}`;
        s: `0x${string}`;
        v: number;
      };
  • cancel

    • The function without a return value to cancel the action on the Ledger device.

4: Sign TypedData

This method enables users to sign an Ethereum message following the EIP-712 specification.

const { observable, cancel } = signerEth.signTypedData(
  derivationPath,
  typedData,
);

Parameters

  • derivationPath

    • Required
    • Type: string (e.g., "44'/60'/0'/0/0")
    • The derivation path used by the Ethereum message. See here for more information.
  • typedData

    • Required

    • Type: TypedData

      interface TypedData {
        domain: TypedDataDomain;
        types: Record<string, Array<TypedDataField>>;
        primaryType: string;
        message: Record<string, unknown>;
      }
       
      interface TypedDataDomain {
        name?: string;
        version?: string;
        chainId?: number;
        verifyingContract?: string;
        salt?: string;
      }
       
      interface TypedDataField {
        name: string;
        type: string;
      }
    • The typed data as defined at EIP-712.

Returns

  • observable

    • An Observable object that contains the DeviceActionState derived instance which reprensents the operation’s state. For example:

      observable.subscribe({
        next: (state: SignTypedDataDAState) => {
          switch (state.status) {
            case DeviceActionStatus.NotStarted: {
              console.log("The action is not started yet.");
              break;
            }
            case DeviceActionStatus.Pending: {
              const { intermediateValue } = state;
              // Access the intermediate value here, explained below
              console.log(
                "The action is pending and the intermediate value is: ",
                requiredUserInteraction,
              );
              break;
            }
            case DeviceActionStatus.Stopped: {
              console.log("The action has been stopped.");
              break;
            }
            case DeviceActionStatus.Completed: {
              const { output } = state;
              // Access the output of the completed action here, explained below
              console.log("The action has been completed: ", output);
              break;
            }
            case DeviceActionStatus.Error: {
              const { error } = state;
              // Access the error here if occured
              console.log("An error occured during the action: ", error);
              break;
            }
          }
        },
      });
    • When the action status is DeviceActionStatus.Pending, the state will include an intermediateValue object that provides useful information for interaction:

      const { requiredUserInteraction } = intermediateValue;
       
      switch (requiredUserInteraction) {
        case UserInteractionRequired.SignTypedData: {
          // User needs to sign the typed data displayed on the device
          console.log(
            "User needs to sign the typed data displayed on the device.",
          );
          break;
        }
        case UserInteractionRequired.None: {
          // No user action required
          console.log("No user action needed.");
          break;
        }
        case UserInteractionRequired.UnlockDevice: {
          // User needs to unlock the device
          console.log("The user needs to unlock the device.");
          break;
        }
        case UserInteractionRequired.ConfirmOpenApp: {
          // User needs to confirm on the device to open the app
          console.log("The user needs to confirm on the device to open the app.");
          break;
        }
        default:
          // Type guard to ensure all cases are handled
          const uncaughtUserInteraction: never = requiredUserInteraction;
          console.error(
            "Unhandled user interaction case:",
            uncaughtUserInteraction,
          );
      }
    • When the action status is DeviceActionStatus.Completed, the execution result can be accessed through the output property in the state. This property is a Signature object with the following structure:

      type Signature = {
        r: `0x${string}`;
        s: `0x${string}`;
        v: number;
      };
  • cancel

    • The function without a return value to cancel the action on the Ledger device.

Example

We encourage you to explore the Ethereum Signer by trying it out in our online sample application. Experience how it works and see its capabilities in action. Of course, you will need a Ledger device connected.

Clear Signing Initiative

As the signer is already integrating the context module. It will also provide the capability of clear sign transaction if we have the data related to the transaction.

Ledger
Copyright © Ledger SAS. All rights reserved. Ledger, Ledger Nano S, Ledger Vault, Ledger OS are registered trademarks of Ledger SAS