From c4d625bc64b51daa24621ba2a9c275cd17b2a70f Mon Sep 17 00:00:00 2001 From: cfranceschi-ledger Date: Mon, 30 Dec 2024 17:21:46 +0100 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=93=9D=20Typos+refactoring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improvements of the Getting started page and the beginners guides. --- .../beginner/discover_and_connect.mdx | 93 ++++++++--- .../beginner/exchange_data.mdx | 155 ++++++------------ .../device-interaction/beginner/init_dmk.mdx | 37 ++++- .../device-interaction/getting-started.mdx | 44 ++--- 4 files changed, 162 insertions(+), 167 deletions(-) diff --git a/pages/docs/device-interaction/beginner/discover_and_connect.mdx b/pages/docs/device-interaction/beginner/discover_and_connect.mdx index 06036d4b..89c7a45c 100644 --- a/pages/docs/device-interaction/beginner/discover_and_connect.mdx +++ b/pages/docs/device-interaction/beginner/discover_and_connect.mdx @@ -1,40 +1,79 @@ +import { Callout } from "nextra/components"; + # Connecting to a Device -There are two steps to connecting to a device: +## Overview + +In this tutorial, you'll learn how to connect to a Ledger device using the Device Management Kit (DMK). We will cover the device discovery and connection process, and how to manage your device session effectively. + +## Prerequisites + +Ensure you have: + +- A device running Ledger firmware. +- The DMK properly set up, as described in the [Setup guide](./init_dmk). + +## Step-by-Step Guide + +### Step 1: Discover Devices -- **Discovery**: `sdk.startDiscovering()` - - Returns an observable which will emit a new `DiscoveredDevice` for every scanned device. - - The `DiscoveredDevice` objects contain information about the device model. - - Use one of these values to connect to a given discovered device. -- **Connection**: `sdk.connect({ deviceId: device.id })` - - Returns a Promise resolving in a device session identifier `DeviceSessionId`. - - **Keep this device session identifier to further interact with the device.** - - Then, `sdk.getConnectedDevice({ sessionId })` returns the `ConnectedDevice`, which contains information about the device model and its name. +Begin by discovering available Ledger devices. Use the `sdk.startDiscovering()` method, which returns an observable. This observable emits a new `DiscoveredDevice` object for each device found. ```ts sdk.startDiscovering().subscribe({ next: (device) => { - sdk.connect({ deviceId: device.id }).then((sessionId) => { - const connectedDevice = sdk.getConnectedDevice({ sessionId }); - }); + // Process each discovered device + console.log(`Discovered device: ${device.model}`); }, error: (error) => { - console.error(error); + console.error("Error during device discovery:", error); }, }); ``` -Then once a device is connected: - -- **Disconnection**: `sdk.disconnect({ sessionId })` -- **Observe the device session state**: `sdk.getDeviceSessionState({ sessionId })` - - This will return an `Observable` to listen to the known information about the device: - - device status: - - ready to process a command - - busy - - locked - - disconnected - - device name - - information on the OS - - battery status - - currently opened app + +- Each `DiscoveredDevice` contains details about the device model and other identification details. +- Use these details to select which device to connect to. + + +### Step 2: Connect to a Device + +After identifying the desired device, initiate a connection using `sdk.connect()`. This method requires the `deviceId` and returns a Promise that resolves with a `DeviceSessionId`. + +```ts +sdk.connect({ deviceId: device.id }).then((sessionId) => { + const connectedDevice = sdk.getConnectedDevice({ sessionId }); + console.log(`Connected to device: ${connectedDevice.name}`); +}); +``` + + + Device Session Identifier**: Store the `DeviceSessionId` securely, as it is needed for further interactions with the device. + + +### Step 3: Interact with the Connected Device + +Once connected, you may wish to observe the device session state or eventually disconnect: + +- **Observe Session State**: Use `sdk.getDeviceSessionState({ sessionId })` to monitor and react to device state changes. This returns an `Observable` that informs about the device's name, status (ready to process command, busy, locked or disconnected), information on the OS, battery status, and currently opened app. + +```ts +sdk.getDeviceSessionState({ sessionId }).subscribe({ + next: (state) => { + console.log("Device status:", state.status); + console.log("Battery level:", state.battery); + } +}); +``` + +- **Disconnect From Device**: When you are done, ensure to disconnect using `sdk.disconnect({ sessionId })`. + +```ts +sdk.disconnect({ sessionId }).then(() => { + console.log("Device disconnected"); +}); +``` +## Best Practices + +- **Session Management**: Maintain the session state to handle connection disruptions or status changes effectively. +- **Error Handling**: Implement robust error-handling mechanisms at each step to ensure smooth operation. \ No newline at end of file diff --git a/pages/docs/device-interaction/beginner/exchange_data.mdx b/pages/docs/device-interaction/beginner/exchange_data.mdx index 6446f7b4..9e388378 100644 --- a/pages/docs/device-interaction/beginner/exchange_data.mdx +++ b/pages/docs/device-interaction/beginner/exchange_data.mdx @@ -1,187 +1,124 @@ +import { Callout } from "nextra/components"; + # Exchange data with the device +## Overview + +This tutorial demonstrates how to send and receive data from a Ledger device using Application Protocol Data Units (APDUs). We'll explore both direct APDU handling and using pre-defined commands for ease of use. + +## Prerequisites + +Make sure you have a connected device session ID available from the previous connection tutorial. + ## Sending an APDU -Once you have a connected device, you can send it APDU commands. +### Recommended Practices + + + Whenever possible, use [pre-defined commands](#sending-a-pre-defined-command) or [custom build commands](#building-a-new-command) rather than dealing with APDUs directly. This approach enhances code reusability and maintainability. + + +### Step 1: Building the APDU -> ℹ️ It is recommended to use the [pre-defined commands](#sending-a-pre-defined-command) when possible, or [build your own command](#building-a-new-command), to avoid dealing with the APDU directly. It will make your code more reusable. +To construct an APDU, use `ApduBuilder`. Here's an example for opening the Bitcoin app: ```ts -import { - ApduBuilder, - ApduParser, - CommandUtils, -} from "@ledgerhq/device-management-kit"; - -// ### 1. Building the APDU -// Use `ApduBuilder` to easily build the APDU and add data to its data field. - -// Build the APDU to open the Bitcoin app -const openAppApduArgs = { - cla: 0xe0, - ins: 0xd8, - p1: 0x00, - p2: 0x00, -}; +import { ApduBuilder } from "@ledgerhq/device-management-kit"; + +const openAppApduArgs = { cla: 0xe0, ins: 0xd8, p1: 0x00, p2: 0x00 }; const apdu = new ApduBuilder(openAppApduArgs) .addAsciiStringToData("Bitcoin") .build(); +``` +### Step 2: Sending the APDU -// ### 2. Sending the APDU +Send the constructed APDU using the `sdk.sendApdu` method: +```ts const apduResponse = await sdk.sendApdu({ sessionId, apdu }); +``` +### Step 3: Parsing the Response + +Parse the response using `ApduParser` and check for success: -// ### 3. Parsing the result +```ts +import { ApduParser, CommandUtils } from "@ledgerhq/device-management-kit"; const parser = new ApduParser(apduResponse); if (!CommandUtils.isSuccessResponse(apduResponse)) { throw new Error( - `Unexpected status word: ${parser.encodeToHexaString( - apduResponse.statusCode, - )}`, + `Unexpected status word: ${parser.encodeToHexaString(apduResponse.statusCode)}`, ); } ``` ## Sending a Pre-defined Command -There are some pre-defined commands that you can send to a connected device. - -The `sendCommand` method will take care of building the APDU, sending it to the device and returning the parsed response. - -> ## ❗️ Error Responses -> -> Most of the commands will reject with an error if the device is locked. -> Ensure that the device is unlocked before sending commands. You can check the device session state (`sdk.getDeviceSessionState`) to know if the device is locked. -> -> Most of the commands will reject with an error if the response status word is not `0x9000` (success response from the device). +For convenience, pre-defined commands simplify APDU building and response parsing. ### Open App -This command will open the app with the given name. If the device is unlocked, it will not resolve/reject until the user has confirmed or denied the app opening on the device. +Opens the specified app on the device: ```ts import { OpenAppCommand } from "@ledgerhq/device-management-kit"; -const command = new OpenAppCommand("Bitcoin"); // Open the Bitcoin app - +const command = new OpenAppCommand("Bitcoin"); await sdk.sendCommand({ sessionId, command }); ``` ### Close App -This command will close the currently opened app. +Closes the currently open app: ```ts import { CloseAppCommand } from "@ledgerhq/device-management-kit"; const command = new CloseAppCommand(); - await sdk.sendCommand({ sessionId, command }); ``` ### Get OS Version -This command will return information about the currently installed OS on the device. - -> ℹ️ If you want this information you can simply get it from the device session state by observing it with `sdk.getDeviceSessionState({ sessionId })`. +Fetches the OS version information: ```ts import { GetOsVersionCommand } from "@ledgerhq/device-management-kit"; const command = new GetOsVersionCommand(); - -const { seVersion, mcuSephVersion, mcuBootloaderVersion } = - await sdk.sendCommand({ sessionId, command }); +const { seVersion, mcuSephVersion, mcuBootloaderVersion } = await sdk.sendCommand({ sessionId, command }); ``` ### Get App and Version -This command will return the name and version of the currently running app on the device. - -> ℹ️ If you want this information you can simply get it from the device session state by observing it with `sdk.getDeviceSessionState({ sessionId })`. +Retrieves the current app name and version: ```ts import { GetAppAndVersionCommand } from "@ledgerhq/device-management-kit"; const command = new GetAppAndVersionCommand(); - const { name, version } = await sdk.sendCommand({ sessionId, command }); ``` -## Sending a Pre-defined flow - Device Actions - -Device actions define a succession of commands to be sent to the device. +## Device Actions -They are useful for actions that require user interaction, like opening an app, -or approving a transaction. - -The result of a device action execution is an observable that will emit different states of the action execution. These states contain information about the current status of the action, some intermediate values like the user action required, and the final result. +Device actions consist of sequences of commands that often require user interaction, such as approving a transaction. ### Open App Device Action ```ts -import { - OpenAppDeviceAction, - OpenAppDAState, -} from "@ledgerhq/device-management-kit"; +import { OpenAppDeviceAction, OpenAppDAState } from "@ledgerhq/device-management-kit"; const openAppDeviceAction = new OpenAppDeviceAction({ appName: "Bitcoin" }); - -const { observable, cancel } = await dmk.executeDeviceAction({ - sessionId, - openAppDeviceAction, -}); +const { observable, cancel } = await dmk.executeDeviceAction({ sessionId, openAppDeviceAction }); observable.subscribe({ - next: (state: OpenAppDAState) => { - switch (state.status) { - case DeviceActionStatus.NotStarted: - console.log("Action not started yet"); - break; - case DeviceActionStatus.Pending: - const { - intermediateValue: { userActionRequired }, - } = state; - switch (userActionRequired) { - case UserActionRequiredType.None: - console.log("No user action required"); - break; - case UserActionRequiredType.ConfirmOpenApp: - console.log( - "The user should confirm the app opening on the device", - ); - break; - case UserActionRequiredType.UnlockDevice: - console.log("The user should unlock the device"); - break; - default: - /** - * you should make sure that you handle all the possible user action - * required types by displaying them to the user. - */ - throw new Exception("Unhandled user action required"); - break; - } - console.log("Action is pending"); - break; - case DeviceActionStatus.Stopped: - console.log("Action has been stopped"); - break; - case DeviceActionStatus.Completed: - const { output } = state; - console.log("Action has been completed", output); - break; - case DeviceActionStatus.Error: - const { error } = state; - console.log("An error occurred during the action", error); - break; - } - }, + // Handle different states such as NotStarted, Pending, Completed, and Error + next: (state: OpenAppDAState) => { /* Handle states */ } }); ``` ### Example in React -Check [the sample app](https://github.com/LedgerHQ/device-sdk-ts/tree/develop/apps/sample) for an advanced example showcasing all possible usages of the Device Management Kit in a React app. +See the [sample app](https://github.com/LedgerHQ/device-sdk-ts/tree/develop/apps/sample) for comprehensive examples showcasing the Device Management Kit's usage in React applications. diff --git a/pages/docs/device-interaction/beginner/init_dmk.mdx b/pages/docs/device-interaction/beginner/init_dmk.mdx index c2e6453b..0a016a65 100644 --- a/pages/docs/device-interaction/beginner/init_dmk.mdx +++ b/pages/docs/device-interaction/beginner/init_dmk.mdx @@ -1,14 +1,21 @@ # Setting up the SDK -The core package exposes an SDK builder `DeviceSdkBuilder` which will be used to initialise the SDK with your configuration. +## Overview -For now it allows you to add one or more custom loggers. +In this tutorial, you'll learn how to set up the Device Management Kit (DMK) SDK in your application. We'll guide you through initializing the SDK using the `DeviceSdkBuilder` and setting up logging. By the end of this tutorial, you will have a singleton instance of the SDK that will serve as the entry point for all interactions. -In the following example, we add a console logger (`.addLogger(new ConsoleLogger())`). Then we build the SDK with `.build()`. +## Prerequisites -**The returned object will be the entrypoint for all your interactions with the SDK. You should keep it as a SINGLETON.** +Before you begin, ensure you have the following: -The SDK should be built only once in your application runtime so keep a reference of this object somewhere. +- A working development environment with Node.js installed. +- Access to the DMK package (@ledgerhq/device-management-kit) in your project. + +## Step-by-Step Guide + +### Step 1: Import Required Components + +Start by importing the necessary components from the DMK package. You'll need `ConsoleLogger`, `DeviceSdk`, and `DeviceSdkBuilder`. ```ts import { @@ -16,8 +23,28 @@ import { DeviceSdk, DeviceSdkBuilder, } from "@ledgerhq/device-management-kit"; +``` + +### Step 2: Initialize the SDK with Configuration + +Use the `DeviceSdkBuilder` to initialize the SDK. You can configure it by adding one or more custom loggers. In this example, we'll add a `ConsoleLogger`. + +```ts +const sdk = new DeviceSdkBuilder() + .addLogger(new ConsoleLogger()) + .build(); +``` + +### Step 3: Maintain a Singleton Instance +The SDK should be instantiated only once during your application's runtime. It's important to keep the returned `DeviceSdk` object as a singleton. Store the reference globally if possible, so it can be reused across your application. + +```ts export const sdk = new DeviceSdkBuilder() .addLogger(new ConsoleLogger()) .build(); ``` + +## Best Practices + +- **Singleton Pattern:** Ensure the SDK instance is maintained as a singleton. This improves efficiency and prevents repeated initializations. diff --git a/pages/docs/device-interaction/getting-started.mdx b/pages/docs/device-interaction/getting-started.mdx index 492ef9fe..b677d647 100644 --- a/pages/docs/device-interaction/getting-started.mdx +++ b/pages/docs/device-interaction/getting-started.mdx @@ -3,48 +3,41 @@ import Image from 'next/image' # Getting started -In this section of the Developer Portal, you will find the all the documention related to the device management kit and all the signers coming along with it. +In this section of the Developer Portal, you will find all the documentation related to the device management kit and all the signers coming along with it. - This project is still in early development so we allow ourselves to make - breaking changes regarding the usage of the Libraries. - -That's why any feedback is relevant for us in order to be able to make it stable as soon as -possible. Get in touch with us on the [Ledger Discord -server](https://developers.ledger.com/discord/) to provide your feedbacks. - -You can follow the migration guidelines [here](./integration/migration/intro) - + This project is currently in the early stages of development. We may introduce breaking changes to the Libraries. + + Your feedback is invaluable and will help us stabilize the project. Please reach out to us on the [Ledger Discord server](https://developers.ledger.com/discord/) to share your thoughts. + + Follow our [migration guidelines](./integration/migration/intro) for seamless updates. -The Device Management Kit will replace the LedgerJS Transport libraries in the future. For any new project, we recommend you use the new Device Management Kit. +The Device Management Kit is set to supersede the LedgerJS Transport libraries. We recommend using the new DMK for all new projects. Although you can still access the previous LedgerJS documentation [here](./ledgerjs/info), consider updating your existing integrations. -For existing projects, you can still access the LedgerJS documentation in [this section](./ledgerjs/info) but we recommend that you consider updating your integration. +To learn about the differences between LDMK and LedgerJS Transport libraries, see [this documentation](./explanation/ledgerjs). -To understand the differences between the LDMK and LedgerJS Transport libraries, read [this documentation](./explanation/ledgerjs). - -The Device Management Kit features are listed [in the References section](./references/dmk). +Explore the features of the Device Management Kit in the [References section](./references/dmk). ## Glossary -Throughout all the documentation we will use several acronyms that you can find the following description : - +We use the following acronyms throughout the documentation: - DMK: Device Management Kit - DSK: Device Signer Kit ## Tools and boilerplates -- To play with our transport librairies and get fimiliar with our tools, we recommend you go through our beginners' guides. -- To start developing your project go to the integration walkthroughs and pick your platform. +- To familiarize yourself with our transport libraries and tools, start with our beginner guides. +- Begin developing your project by visiting the integration walkthroughs and selecting your platform. ## Libraries -Here you can found a summary of all the libraries that are composing the DMK +Below is a summary of the libraries included in the DMK: | Library | NPM | Version | | ---------------------- | ---------------------------------------------------------------------------------------------------------- | ------- | -| Device Management Kit | [@LedgerHQ/device-mangement-kit](https://www.npmjs.com/package/@ledgerhq/device-management-kit) | 0.4.0 | +| Device Management Kit | [@LedgerHQ/device-management-kit](https://www.npmjs.com/package/@ledgerhq/device-management-kit) | 0.4.0 | | Device Signer Ethereum | [@LedgerHQ/device-signer-kit-ethereum](https://www.npmjs.com/package/@ledgerhq/device-signer-kit-ethereum) | 1.0.0 | | Context Module | [@LedgerHQ/context-module](https://www.npmjs.com/package/@ledgerhq/context-module) | 1.0.0 | @@ -53,11 +46,11 @@ Here you can found a summary of all the libraries that are composing the DMK ### Description -This package contains the core of the Device Management Kit. It provides a simple interface to handle Ledger devices and features the Device Management Kit's entry points, classes, types, structures, and models. +The Device Management Kit package provides a straightforward interface for handling Ledger devices. It includes essential entry points, classes, types, structures, and models. ### Installation -To install the dmk package, run the following command: +Install the DMK package with the following command: ```sh npm install @ledgerhq/device-management-kit @@ -67,9 +60,8 @@ npm install @ledgerhq/device-management-kit #### Compatibility -This library works in [any browser supporting the WebHID API](https://developer.mozilla.org/en-US/docs/Web/API/WebHID_API#browser_compatibility). +This library is compatible with [browsers supporting the WebHID API](https://developer.mozilla.org/en-US/docs/Web/API/WebHID_API#browser_compatibility). #### Pre-requisites -Some of the APIs exposed return objects of type `Observable` from RxJS. Ensure you are familiar with the basics of the Observer pattern and RxJS before using this SDK. You can refer to [RxJS documentation](https://rxjs.dev/guide/overview) for more information. - +Some API methods return `Observable` objects from RxJS. Familiarize yourself with the Observer pattern and RxJS basics before using this SDK. Refer to the [RxJS documentation](https://rxjs.dev/guide/overview) for more information. From a36c4994ecd84cb638c81a70f1d64ae4d0d9e433 Mon Sep 17 00:00:00 2001 From: cfranceschi-ledger Date: Tue, 31 Dec 2024 09:28:34 +0100 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=93=9D=20Complete=20third=20beginner'?= =?UTF-8?q?s=20guide?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../beginner/exchange_data.mdx | 83 +++++++++++++++++-- 1 file changed, 76 insertions(+), 7 deletions(-) diff --git a/pages/docs/device-interaction/beginner/exchange_data.mdx b/pages/docs/device-interaction/beginner/exchange_data.mdx index 9e388378..85a96c6a 100644 --- a/pages/docs/device-interaction/beginner/exchange_data.mdx +++ b/pages/docs/device-interaction/beginner/exchange_data.mdx @@ -57,9 +57,15 @@ if (!CommandUtils.isSuccessResponse(apduResponse)) { For convenience, pre-defined commands simplify APDU building and response parsing. + + Most of the commands will reject with an error if the device is locked. Ensure that the device is unlocked before sending commands. You can check the device session state (sdk.getDeviceSessionState) to know if the device is locked. + + Most of the commands will reject with an error if the response status word is not 0x9000 (success response from the device). + + ### Open App -Opens the specified app on the device: +Opens the app with the given name: ```ts import { OpenAppCommand } from "@ledgerhq/device-management-kit"; @@ -68,6 +74,8 @@ const command = new OpenAppCommand("Bitcoin"); await sdk.sendCommand({ sessionId, command }); ``` +If the device is unlocked, it does not resolve/reject until the user has confirmed or denied the app opening on the device. + ### Close App Closes the currently open app: @@ -90,6 +98,10 @@ const command = new GetOsVersionCommand(); const { seVersion, mcuSephVersion, mcuBootloaderVersion } = await sdk.sendCommand({ sessionId, command }); ``` + + If you want this information you can simply get it from the device session state by observing it with `sdk.getDeviceSessionState({ sessionId })`. + + ### Get App and Version Retrieves the current app name and version: @@ -100,22 +112,79 @@ import { GetAppAndVersionCommand } from "@ledgerhq/device-management-kit"; const command = new GetAppAndVersionCommand(); const { name, version } = await sdk.sendCommand({ sessionId, command }); ``` + + If you want this information you can simply get it from the device session state by observing it with `sdk.getDeviceSessionState({ sessionId })`. + + +## Sending a Pre-defined flow - Device Actions + +Device actions define a succession of commands to be sent to the device. -## Device Actions +They are useful for actions that require user interaction, like opening an app, +or approving a transaction. -Device actions consist of sequences of commands that often require user interaction, such as approving a transaction. +The result of a device action execution is an observable that will emit different states of the action execution. These states contain information about the current status of the action, some intermediate values like the user action required, and the final result. ### Open App Device Action ```ts -import { OpenAppDeviceAction, OpenAppDAState } from "@ledgerhq/device-management-kit"; +import { + OpenAppDeviceAction, + OpenAppDAState, +} from "@ledgerhq/device-management-kit"; const openAppDeviceAction = new OpenAppDeviceAction({ appName: "Bitcoin" }); -const { observable, cancel } = await dmk.executeDeviceAction({ sessionId, openAppDeviceAction }); + +const { observable, cancel } = await dmk.executeDeviceAction({ + sessionId, + openAppDeviceAction, +}); observable.subscribe({ - // Handle different states such as NotStarted, Pending, Completed, and Error - next: (state: OpenAppDAState) => { /* Handle states */ } + next: (state: OpenAppDAState) => { + switch (state.status) { + case DeviceActionStatus.NotStarted: + console.log("Action not started yet"); + break; + case DeviceActionStatus.Pending: + const { + intermediateValue: { userActionRequired }, + } = state; + switch (userActionRequired) { + case UserActionRequiredType.None: + console.log("No user action required"); + break; + case UserActionRequiredType.ConfirmOpenApp: + console.log( + "The user should confirm the app opening on the device", + ); + break; + case UserActionRequiredType.UnlockDevice: + console.log("The user should unlock the device"); + break; + default: + /** + * you should make sure that you handle all the possible user action + * required types by displaying them to the user. + */ + throw new Exception("Unhandled user action required"); + break; + } + console.log("Action is pending"); + break; + case DeviceActionStatus.Stopped: + console.log("Action has been stopped"); + break; + case DeviceActionStatus.Completed: + const { output } = state; + console.log("Action has been completed", output); + break; + case DeviceActionStatus.Error: + const { error } = state; + console.log("An error occurred during the action", error); + break; + } + }, }); ``` From 053d56162ac5825a829412627fcac233d2756d25 Mon Sep 17 00:00:00 2001 From: cfranceschi-ledger Date: Tue, 31 Dec 2024 10:15:38 +0100 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=93=9D=20Walkthrough=20updates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integration/ldmk/build_custom_command.mdx | 20 +++++---- .../integration/ldmk/how_to_use_a_signer.mdx | 41 +++++++++++++------ 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/pages/docs/device-interaction/integration/ldmk/build_custom_command.mdx b/pages/docs/device-interaction/integration/ldmk/build_custom_command.mdx index 6c6c9a2b..e2797725 100644 --- a/pages/docs/device-interaction/integration/ldmk/build_custom_command.mdx +++ b/pages/docs/device-interaction/integration/ldmk/build_custom_command.mdx @@ -2,17 +2,17 @@ import { Callout } from "nextra/components"; # Build a Custom Command -## Method +## Overview -To build your own command: +To build your a custom command for interacting with a connected Ledger device: 1. Extend the `Command` class and implement the `getApdu` and `parseResponse` methods 2. Use the the `sendCommand` method to send it to a connected device - -This is strongly recommended over direct usage of `sendApdu`. Note : Explain why. - +## Why Use Custom Commands? -### Examples +Custom commands are preferable over the direct use of `sendApdu` because they encapsulate command logic, enhance reusability, and simplify error handling. This method abstracts the complexity of APDU interaction, making your code more maintainable and easier to understand. + +## Example: MyCustomCommand Implementation ```typescript export class MyCustomCommand @@ -74,6 +74,10 @@ export class MyCustomCommand } ``` -## Usage of ApduBuilder +## Utilizing `ApduBuilder` + +The `ApduBuilder` simplifies the construction of APDUs by providing methods to append different types of data. This abstraction allows for clean and organized command structures that can be easily maintained and understood. + +## Utilizing `ApduParser` -## Usage of ApduParser +The `ApduParser` provides methods to deconstruct device responses systematically. It ensures that status words are checked efficiently and handles any parsing logic, leading to cleaner and more robust response processing. diff --git a/pages/docs/device-interaction/integration/ldmk/how_to_use_a_signer.mdx b/pages/docs/device-interaction/integration/ldmk/how_to_use_a_signer.mdx index c31f64d2..54eb4aae 100644 --- a/pages/docs/device-interaction/integration/ldmk/how_to_use_a_signer.mdx +++ b/pages/docs/device-interaction/integration/ldmk/how_to_use_a_signer.mdx @@ -2,16 +2,18 @@ import { Callout } from "nextra/components"; # Use a signer - - We will show the usage of the signer with the Ethereum signer. The same logic can be applied to the other signers. - +## Overview -## Installation +This guide demonstrates how to utilize an Ethereum signer with Ledger devices. The principles outlined apply to other signers as well. + +## Prerequisite - This module is not standalone; it depends on the [@ledgerhq/device-management-kit](https://github.com/LedgerHQ/device-sdk-ts/tree/develop/packages/device-management-kit) package, so you need to install it first. + The Ethereum signer module is not a standalone package. It requires the [Device Management Kit](https://github.com/LedgerHQ/device-sdk-ts/tree/develop/packages/device-management-kit) as a dependency. Ensure this package is installed in your project before proceeding. +## Installation + To install the `device-signer-kit-ethereum` package, run the following command: ```sh @@ -20,17 +22,33 @@ npm install @ledgerhq/device-signer-kit-ethereum ## Usage -To initialize an Ethereum signer instance, you need a Ledger Device Management Kit instance and the ID of the session of the connected device. Use the `SignerEthBuilder` along with the [Context Module](https://github.com/LedgerHQ/device-sdk-ts/tree/develop/packages/signer/context-module) by default developed by Ledger: +To create an instance of the Ethereum signer, you need: + +- A configured instance of the Ledger Device Management Kit +- A session ID from a connected device session + +### Example with Default Context Module + +The following example illustrates how to initialize an Ethereum signer using the default context module provided by Ledger: ```typescript -// Initialize an Ethereum signer instance using default context module +import { SignerEthBuilder } from "@ledgerhq/device-signer-kit-ethereum"; + +// Initialize an Ethereum signer instance const signerEth = new SignerEthBuilder({ sdk, sessionId }).build(); ``` -You can also configure the context module yourself: +### Example with Custom Context Module + +Alternatively, you can customize the context module to suit your specific needs: ```typescript -// Initialize an Ethereum signer instance using customized context module +import { SignerEthBuilder } from "@ledgerhq/device-signer-kit-ethereum"; + +// Customize the context module +const customContextModule = /* your custom context logic */; + +// Initialize an Ethereum signer instance with custom context const signerEth = new SignerEthBuilder({ sdk, sessionId }) .withContextModule(customContextModule) .build(); @@ -38,6 +56,5 @@ const signerEth = new SignerEthBuilder({ sdk, sessionId }) ## Reference -Find the signers features in the references section: -- [Ethereum signer](../../references/signers/eth) -- More signers to come... \ No newline at end of file +- [Ethereum Signer Features](../../references/signers/eth). Explore the features and capabilities available for the Ethereum signer. +- **Upcoming Signers:** Stay tuned for more signers to be added in the future. From 8cf65707f6e6bdbedf65d95c5bddf9d5c5eb25d1 Mon Sep 17 00:00:00 2001 From: cfranceschi-ledger Date: Tue, 31 Dec 2024 16:42:48 +0100 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=93=9D=20DMK=20reference=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../device-interaction/references/dmk.mdx | 69 +++++++++---------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/pages/docs/device-interaction/references/dmk.mdx b/pages/docs/device-interaction/references/dmk.mdx index 881254b3..5a9a6b49 100644 --- a/pages/docs/device-interaction/references/dmk.mdx +++ b/pages/docs/device-interaction/references/dmk.mdx @@ -2,57 +2,57 @@ import { Callout } from "nextra/components"; # Device Management Kit -The device management kit is the entry point for all the other libraries related to it. -As we wanted to make the project modular. +The Device Management Kit (DMK) serves as the foundational entry point for interfacing with Ledger devices. Designed with modularity in mind, it integrates with various libraries to facilitate device management. ## Main Features -- Discovering and connecting to Ledger devices via USB, through [WebHID](https://developer.mozilla.org/en-US/docs/Web/API/WebHID_API). -- Discovering and connecting to Ledger devices via BLE, through [WebBLE](https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API). -- Observing the state of a connected device. -- Sending custom APDU commands to Ledger devices. -- Sending a set of pre-defined commands to Ledger devices. - - Get OS version - - Get app and version - - Open app - - Close app - - Get battery status -- Execute a flow of commands with **DeviceAction**. +- **Device Discovery and Connection**: + - Connect to Ledger devices via USB using [WebHID](https://developer.mozilla.org/en-US/docs/Web/API/WebHID_API). + - Connect via Bluetooth Low Energy (BLE) using [WebBLE](https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API). +- **Device State Observation**: + - Monitor the state of connected Ledger devices. +- **APDU Command Execution**: + - Send custom Application Protocol Data Units (APDU) commands. +- **Pre-defined Commands Execution**: + - Retrieve OS version, app and version information. + - Open or close an app. + - Get device battery status. +- **DeviceAction Execution**: + - Perform sequences of commands as defined by **DeviceAction**. -> [!NOTE] -> At the moment we do not provide the possibility to distinguish two devices of the same model, via WebHID and to avoid connection to the same device twice. + +At the moment we do not provide the possibility to distinguish two devices of the same model via WebHID to prevent connecting to the same device twice. + -## Communicate with a Ledger device +## Communication with a Ledger device -The DMK is offering several ways to communicate with a Ledger device. +The DMK provides multiple methods to interact with Ledger devices. -### Send APDU +### Sending APDU Commands - - This method is not recommended for most of the use cases. We recommend using - the _Command_ or _DeviceAction_ instead. + + Direct APDU command usage is generally not recommended for typical use cases. Prefer >using or DeviceAction methods for simplicity and reliability. You can send APDU commands to the device using the `sendApdu` method of the Device Management Kit instance (here `dmk`) instance. **Parameters**: -- `sessionId`: string - The session ID, identifier of the connection with a device. -- `apdu`: UInt8Array - bytes array of data to be send to the device. +- `sessionId`: *string* - Identifier of the device connection session. +- `apdu`: *UInt8Array* - Data bytes array to send to the device. ```typescript await dmk.sendApdu({ sessionId, apdu }); ``` -### Commands +### Executing Commands Commands are pre-defined actions that you can send to the device. -You can use the `sendCommand` method of the `dmk` instance to send a command to the device. +Use the `sendCommand` method of the `dmk` instance to send a command to the device. **Parameters**: - -- `sessionId`: string - The session ID, which an identifier of the connection with a device. -- `command`: Command - The command to be sent to the device. +- `sessionId`: *string* - Identifier of the device connection session. +- `command`: *Command* - Command to be sent to the device. ```typescript import { OpenAppCommand } from "@ledgerhq/device-management-kit"; @@ -61,7 +61,7 @@ const command = new OpenAppCommand("Bitcoin"); // Open the Bitcoin app await dmk.sendCommand({ sessionId, command }); ``` -### Device Actions +### Executing device Actions Device actions are a set of commands that are executed in a sequence. You can use the `executeDeviceAction` method of the `dmk` instance to execute a device action. @@ -70,9 +70,8 @@ It is returning an observable that will emit different states of the action exec A device action is cancellable, you can cancel it by calling the `cancel` function returned by the `executeDeviceAction` method. **Parameters**: - -- `sessionId`: string - The session ID, which an identifier of the connection with a device. -- `deviceAction`: DeviceAction - The DeviceAction to be sent to the device. +- `sessionId`: *string* - Identifier of the device connection session. +- `deviceAction`: *DeviceAction* - The`DeviceAction` to be sent to the device. ```typescript const openAppDeviceAction = new OpenAppDeviceAction({ appName: "Bitcoin" }); @@ -85,11 +84,9 @@ const { observable, cancel } = await dmk.executeDeviceAction({ ## State Management -For each connected device, we are managing and providing a device state. - -The different states are: +Monitor and manage device states during interaction: - `connected`: The device is connected. - `locked`: The device is locked. User needs to unlock it to perform operations. -- `busy`: The device is busy, so not reachable. +- `busy`: The device is busy, hence not reachable. - `disconnected`: The device is disconnected. From 84c1fa800f1e2a55e0cf3955511b6a9167831438 Mon Sep 17 00:00:00 2001 From: cfranceschi-ledger Date: Tue, 31 Dec 2024 17:29:08 +0100 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=93=9D=20Update=20and=20refactoring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../device-interaction/explanation/_meta.js | 2 +- .../explanation/introduction.mdx | 22 +++++++--- .../explanation/ledgerjs.mdx | 40 ++++++++++--------- .../explanation/signers.mdx | 15 +++++-- .../device-interaction/references/dmk.mdx | 8 ++-- .../references/signers/eth.mdx | 2 +- 6 files changed, 55 insertions(+), 34 deletions(-) diff --git a/pages/docs/device-interaction/explanation/_meta.js b/pages/docs/device-interaction/explanation/_meta.js index 420b4d14..d9afabe8 100644 --- a/pages/docs/device-interaction/explanation/_meta.js +++ b/pages/docs/device-interaction/explanation/_meta.js @@ -1,5 +1,5 @@ export default { - introduction: "Why the Device Management Kit?", + introduction: "Why choose the Device Management Kit?", signers: "What are Device Signer Kits?", ledgerjs: "Differences with LedgerJS" }; diff --git a/pages/docs/device-interaction/explanation/introduction.mdx b/pages/docs/device-interaction/explanation/introduction.mdx index 2f5b7590..707d1aeb 100644 --- a/pages/docs/device-interaction/explanation/introduction.mdx +++ b/pages/docs/device-interaction/explanation/introduction.mdx @@ -1,9 +1,21 @@ -# Why Device Management Kit ? +# Why choose the Device Management Kit? -The DMK is a set of tools and libraries that allow you to manage your devices in a secure and efficient way. It is designed to be used in conjunction with the Device Signer Kit, which is a set of tools and libraries that allow you to sign transactions securely. +The Device Management Kit (DMK) offers a comprehensive suite of tools and libraries tailored for secure and efficient management of Ledger devices. It is specifically crafted for external developers to enhance the experience of interacting with Ledger hardware securely. -It has been designed for external developers with the main idea to provide the best experience for developers to interact with Ledger devices. +## Seamless Integration with Device Signer Kit -It should as maximum as possible abstract the complexity of the communication with the device and provide a simple and easy-to-use API. +The DMK works seamlessly with the Device Signer Kit, providing a robust ecosystem for secure transaction signing. This integration ensures that developers have access to comprehensive tools for both device management and transaction handling. -It tends to be a replacement for the LedgerJS libraries, mainly `hw-app-XXX` and `transport-XXX` libraries. These libraries are intended to be deprecated in the future. +## Developer-Centric Design + +The DMK is purpose-built for developers, focusing on simplifying interactions with Ledger devices. By providing an intuitive and straightforward API, the DMK abstracts much of the underlying complexity involved in device communication, empowering developers to integrate Ledger functionalities with ease. + +## Simplified Device Interaction + +One of the core objectives of the DMK is to remove the complexities associated with device communication. Its user-friendly API is designed to provide a simple and efficient way to manage Ledger hardware, allowing developers to focus on building applications rather than dealing with low-level device interactions. + +## Future-Proof Solution + +The DMK is intended to replace existing LedgerJS libraries, such as `hw-app-XXX` and `transport-XXX`. As these older libraries are set to be deprecated, adopting the DMK represents a forward-looking solution that aligns with Ledger's evolving technology stack, preparing developers for future updates and innovations. + +By choosing the Device Management Kit, developers can leverage a powerful, secure, and developer-focused toolkit that simplifies the integration with Ledger devices and supports the secure signing of transactions. \ No newline at end of file diff --git a/pages/docs/device-interaction/explanation/ledgerjs.mdx b/pages/docs/device-interaction/explanation/ledgerjs.mdx index 97c5a018..39e5faba 100644 --- a/pages/docs/device-interaction/explanation/ledgerjs.mdx +++ b/pages/docs/device-interaction/explanation/ledgerjs.mdx @@ -1,32 +1,34 @@ # Differences with LedgerJS -Device management kit aims to replace LedgerJS libraries, mainly `hw-app-XXX` and `hw-transport-XXX` libraries +The Device Management Kit (DMK) is designed to replace the existing LedgerJS libraries, including the `hw-app-XXX` and `hw-transport-XXX` series. -## Current Problems +## Legacy Challenges -Ledger JS libraries where initially made for **Ledger Live** applications. As Ledger Live is a pretty old project (> 7 years), -we have inevitably a big technical debt. Moreover time make that some part of the logic are today hard to understand and to maintain. +The LedgerJS libraries were originally developed to support **Ledger Live** applications. Given that Ledger Live has been evolving for over seven years, the libraries have accumulated technical debt over this extensive period. Consequently, some components of the libraries have grown more complex, making them challenging to maintain and extend. -Some device behavior are not correctly handled by the libraries, for example opening an application on the device will cause unexpected disconnection. -Another feedback we have learnt from partners (software wallets) is that we have a lack of simplicity in the libraries, it requires low level knowledge to use them (ex: APDU concept). +A few behaviors in the device libraries do not align perfectly with expected outcomes. For example, the act of opening an application on the device might lead to unanticipated disconnections. -## Target +Additionally, feedback from our partners, including software wallet developers, indicates that the libraries could benefit from enhanced simplicity and a reduction in the need for low-level programming knowledge (such as understanding the APDU communication protocol). -LedgerJS was intended for Ledger Live. It was not designed to be used by third party developers. -With the Device Management Kit we are targeting **third party developers first**. -## Abstract complexity +## Target Audience -As said above, we wanted to reduce the entry level to interact with Ledger devices. -So we have tried as much as possible to abstract the complexity of the communication with the device and provide a simple and easy-to-use API. +While LedgerJS was primarily designed for use with Ledger Live, the Device Management Kit is specifically tailored to prioritize the needs of **third-party developers**. -## Multiple Connected devices +## Simplifying Interactions -With LedgerJS, it was impossible to be connected at the same time to two devices. -With DMK, we have made it possible to connect to multiple devices at the same time and interact from one to another. +Our goal with the DMK is to significantly lower the barrier for developers interacting with Ledger devices. +By abstracting much of the underlying complexity, the DMK provides a straightforward and user-friendly API, facilitating easier integration. -## When prefer LedgerJS instead of DMK ? +## Support for Multiple Devices -As we are still missing some features in DMK, you may still need to use LedgerJS in some cases. -For example, we are missing signer for some blockchains, so you may still need to use LedgerJS to sign transactions. -Some solutions are studied at the moment to provide a better compatibility between DMK and LedgerJS. +LedgerJS restricted simultaneous connections to multiple devices. In contrast, the DMK introduces the ability to connect and interact with multiple devices concurrently, enhancing multi-device management capabilities. + +## When to Use LedgerJS Instead of DMK + +While the DMK offers advanced features, there are certain scenarios where LedgerJS may still be necessary due to current feature gaps in the DMK. +For example, the DMK is still expanding its support for signers specific to certain blockchains. In such cases, continuing to use LedgerJS for transaction signing might be beneficial. +We are actively working on solutions to bridge these gaps and improve compatibility between the DMK and LedgerJS. + +In summary, the DMK represents a modern solution tailored to current development needs, with a focus on ease of use and expanded functionality. +As we continue to enhance its features, we are committed to maintaining compatibility with existing solutions. diff --git a/pages/docs/device-interaction/explanation/signers.mdx b/pages/docs/device-interaction/explanation/signers.mdx index 7c21a1b3..66018da6 100644 --- a/pages/docs/device-interaction/explanation/signers.mdx +++ b/pages/docs/device-interaction/explanation/signers.mdx @@ -1,11 +1,18 @@ + # What are Device Signer Kits? -As ledger devices are able to install applications that will allow to be compatible with different blockchains, we have created Device Signer Kits. +Device Signer Kits are designed to facilitate seamless interactions with Ledger devices across various blockchain applications. As Ledger devices can support multiple blockchain technologies through the installation of specific applications, Device Signer Kits provide the necessary tools to efficiently manage these interactions. -Each **signer kit** is coming along with a Ledger Embedded App (ex: _signer-kit-eth_ is coming with _ledger app ethereum_ ). +## Purpose of Device Signer Kits -The main goal of each signer is to ease interaction with the app in the most seamless way possible. +Each Device Signer Kit is paired with a corresponding Ledger Embedded App, enabling compatibility with specific blockchains. For example, the `signer-kit-eth` is used in conjunction with the Ledger Ethereum app, ensuring that developers can interact with Ethereum blockchain functionalities directly through their Ledger devices. +The primary objective of each signer kit is to streamline communication with the Ledger device's applications. By abstracting the complexities of blockchain integration, these kits offer a user-friendly API that allows developers to focus on building their blockchain applications without worrying about the intricacies of device communication. ## Available Signers -- [Signer Ethereum](../references/signers/eth) +- **Ethereum Signer**: Facilitates interactions with the Ethereum blockchain through the Ledger Ethereum app. It encapsulates the necessary protocols and commands to manage Ethereum transactions and smart contract interactions seamlessly. + + + +By utilizing Device Signer Kits, developers gain access to a set of comprehensive tools that simplify the process of managing blockchain interactions on Ledger devices, promoting efficient and secure application development. + diff --git a/pages/docs/device-interaction/references/dmk.mdx b/pages/docs/device-interaction/references/dmk.mdx index 5a9a6b49..2715282b 100644 --- a/pages/docs/device-interaction/references/dmk.mdx +++ b/pages/docs/device-interaction/references/dmk.mdx @@ -31,10 +31,10 @@ The DMK provides multiple methods to interact with Ledger devices. ### Sending APDU Commands - Direct APDU command usage is generally not recommended for typical use cases. Prefer >using or DeviceAction methods for simplicity and reliability. + Direct APDU command usage is generally not recommended for typical use cases. Prefer using Command or DeviceAction methods for simplicity and reliability. -You can send APDU commands to the device using the `sendApdu` method of the Device Management Kit instance (here `dmk`) instance. +You can send APDU commands to the device using the `sendApdu` method of the Device Management Kit instance (here `dmk`). **Parameters**: @@ -66,12 +66,12 @@ await dmk.sendCommand({ sessionId, command }); Device actions are a set of commands that are executed in a sequence. You can use the `executeDeviceAction` method of the `dmk` instance to execute a device action. -It is returning an observable that will emit different states of the action execution. +It returns an observable that emits different states of the action execution. A device action is cancellable, you can cancel it by calling the `cancel` function returned by the `executeDeviceAction` method. **Parameters**: - `sessionId`: *string* - Identifier of the device connection session. -- `deviceAction`: *DeviceAction* - The`DeviceAction` to be sent to the device. +- `deviceAction`: *DeviceAction* - The `DeviceAction` to be sent to the device. ```typescript const openAppDeviceAction = new OpenAppDeviceAction({ appName: "Bitcoin" }); diff --git a/pages/docs/device-interaction/references/signers/eth.mdx b/pages/docs/device-interaction/references/signers/eth.mdx index ed6e5be4..2f1dda15 100644 --- a/pages/docs/device-interaction/references/signers/eth.mdx +++ b/pages/docs/device-interaction/references/signers/eth.mdx @@ -530,7 +530,7 @@ const { observable, cancel } = signerEth.signTypedData( ## Example -We encourage you to explore the Ethereum Signer by trying it out in our online [sample application](https://app.devicesdk.ledger.com/). Experience how it works and see its capabilities in action. Of course, you will need a Ledger device connected. +We encourage you to explore the Ethereum Signer by trying it out in our online [sample application](https://app.devicesdk.ledger.com/). Experience how it works and see its capabilities in action. You will need a Ledger device connected. ## Clear Signing Initiative