mcpField
L
ledger-dmk-implementation

ledger-dmk-implementation

github.com/ledgerhq开发7101 次安装2 周前更新
代码仓库

关于 ledger-dmk-implementation

面向开发者的流程技能,用于通过 Device Management Kit(DMK)执行 Ledger 硬件操作。它要求依次检查初始化、设备会话与状态、应用就绪情况,并等待用户批准签名或设备管理操作。

主要功能

  1. 01按顺序执行操作前检查
  2. 02发现设备并验证会话
  3. 03处理应用打开与状态
  4. 04执行签名和设备管理流程
  5. 05分类超时与错误
  6. 06强制升级至人工处理

适用场景

  1. 01构建 Ledger 签名流程
  2. 02处理设备发现与连接
  3. 03操作前确认应用就绪
  4. 04向编排器返回结构化错误

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ledgerhq/agent-skills --skill ledger-dmk-implementation

安装后在 Claude Code 中输入/ledger-dmk-implementation确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

dmk-code-patterns.md
dmk-platform-patterns.md
dmk-sdk-reference.md

详细介绍

DMK 签名流程

本技能将介绍安全执行 Ledger 硬件操作所需的所有关卡——从 SDK 初始化和设备会话,到状态和应用检查,再到签名或设备管理——并返回结果。每一步都是一道关卡,不可跳过。如果请求措辞随意或意图不明确,请先加载 dmk-intent-vocabulary 技能。


连接器

相关技能:

  • dmk-intent-vocabulary — 意图识别和 API 词汇。请求含糊不清时使用。
  • dmk-business-logic — 概念参考:Clear Signing、Secure Channel、Device Actions 与 Commands、会话、传输方式、派生路径、Ledger OS、Genuine Check。开发者询问“X 是什么?”或需要了解 API 决策背后的原因时加载。

参考文件:

  • dmk-sdk-reference.md — 软件包版本、概念图谱、链路路由、派生路径来源。在步骤 1(版本检查)和步骤 5(链路路由和签名器选择)加载。
  • dmk-code-patterns.md — DMK 初始化、设备发现、可观察对象订阅以及各链签名器用法的具体代码。在步骤 1(SDK 初始化)、步骤 2(发现和连接模式)以及步骤 5(操作模式)加载。
  • dmk-platform-patterns.md — React(DmkProvider、钩子、组件)、Node.js CLI、Vite 配置、EIP-1193 provider。目标平台已知时加载。

生成代码前需要核实的来源:

  • SDK 根目录:https://github.com/LedgerHQ/device-sdk-ts
  • 示例应用:https://github.com/LedgerHQ/device-sdk-ts/tree/develop/apps/sample — 权威用法模式。只阅读设备交互代码,忽略 Redux/Next.js 封装。
  • npm 类型定义 — 已安装版本的权威 API 参考。当版本不同时,优先于 GitHub 源码。

运行时依赖:

  • 浏览器:WebHID/WebBLE——仅限 Chromium(Chrome、Edge、Brave),需使用 HTTPS 或 localhost。必须通过用户手势调用 startDiscovering() 和 connect()。否则会静默失败。
  • Node.js / Electron:Node-HID 传输
  • React Native:BLE 或 React Native HID 传输

流程

约定:

  • → PROCEED — 条件满足,进入下一步
  • → WAIT(Ns) — 订阅或轮询,最长 N 秒
  • → ABORT — 停止,向编排器返回结构化错误
  • → ESCALATE — 停止,转交人工处理,不要重试

每次硬件操作前都要执行步骤 1–4。各关卡按顺序执行——通过当前步骤后才能继续。


步骤 1 — SDK 初始化

HITL: 否 参考: dmk-sdk-reference.md(软件包版本、概念图谱)· dmk-code-patterns.md(初始化模式)· 若平台已知,则参考 dmk-platform-patterns.md

DMK 单例存在且非 null → PROCEED 进入步骤 2

尚未初始化:

  • 根据运行环境选择传输方式(见“连接器”→“运行时依赖”)
  • 初始化并确认实例非 null
  • 抛出异常或返回 null → ABORT:“DMK 初始化失败——此运行时可能无法使用 WebHID”

步骤 2 — 设备会话

**HITL:**是 — 浏览器选择器需要用户手势;有多台设备时需要人工选择
参考:dmk-code-patterns.md(发现和连接模式)· @ledgerhq/device-management-kit 类型

作用域内存在活动的 sessionId → 使用 dmk.getDeviceSessionState({ sessionId }) 验证,获取首次发出的状态,然后取消订阅:

  • 不是 Disconnected → 继续执行步骤 3
  • Disconnected → 清除 sessionId,转而进行设备发现

不存在 sessionId → dmk.startDiscovering({ transport: webHidIdentifier }):

  • 15 秒内未发现设备 → 中止:"未检测到 Ledger 设备"
  • 1 台设备 → 取消订阅 → dmk.connect({ device, sessionRefresherOptions: { isRefresherDisabled: false } }) → 存储 sessionId → 继续执行步骤 3
  • 2 台或更多设备 → 取消订阅 → 升级处理:"检测到多台 Ledger 设备 — 无法自主选择"
  • 发现或连接时抛出异常 → 中止,并提供错误详情

注意:WebHID 浏览器选择器可确保恰好选择一台设备。对于 BLE 或会发出多个事件的传输方式,请在首次发出事件后等待 5 秒再作判断。


步骤 3 — 设备状态

**HITL:**是 — 设备锁定时,用户必须输入 PIN
参考:@ledgerhq/device-management-kit 中的 DeviceSessionState 类型

订阅 dmk.getDeviceSessionState({ sessionId }),获取首次发出的状态,然后取消订阅:

状态操作
Ready→ 继续执行步骤 4
Busy→ 等待(10 秒),然后重新检查一次。仍处于忙碌状态 → 中止:"设备正忙"
Locked→ 升级处理:"设备已锁定 — 用户必须输入 PIN"
Disconnected→ 中止:"设备已断开连接"

步骤 4 — 应用管理

**HITL:**是 — 用户必须确认设备上已打开应用;设备可能会在此步骤中途锁定
参考:@ledgerhq/device-management-kit 中的 OpenAppDeviceAction、GetAppAndVersionCommand;dmk-sdk-reference.md(链路路由)

从会话状态读取 state.currentApp.name(使用相同的订阅、获取首次发出的状态和取消订阅模式):

当前状态操作
已打开正确的应用→ 继续执行步骤 5
已打开错误的应用sendCommand(CloseAppCommand) → 打开正确的应用
未打开应用(控制面板)→ 打开正确的应用

通过 OpenAppDeviceAction 打开应用 — 订阅并处理每个状态:

状态用户交互操作
PendingNone等待
PendingConfirmOpenApp等待最多 30 秒,让用户在设备上确认
PendingUnlockDevice→ 升级处理:"打开应用期间设备已锁定"
Completed—→ 继续执行步骤 5
Stopped—→ 中止:"打开应用已取消"
Error—→ 分类处理(参见规则 → 错误分类)

经过 30 秒后仍未出现 Completed 或 Error → cancel() → 中止:"打开应用超时"


第 5 步 — 操作

HITL: 是 — 用户必须在设备上批准每项操作
参考: dmk-sdk-reference.md(链路路由、签名器构建器、派生路径来源)· dmk-code-patterns.md(签名器初始化、可观察对象订阅、安全通道模式)· 链签名器套件类型

初始化签名器:new [Chain]SignerBuilder({ dmk, sessionId }).build()

调用操作方法。订阅返回的可观察对象:

状态用户交互操作
NotStarted—等待
PendingNone等待
PendingUnlockDevice→ 升级处理:“签名期间设备已锁定”
PendingConfirmTransactionData 或等效操作等待用户批准,最长 60s
Completed—提取 state.output → 返回给编排器
Stopped—→ 中止:“操作已停止”
Error—→ 分类(参见规则 → 错误分类)

经过 60s → cancel() → 升级处理:“操作超时 — 用户未响应”

链特定说明:

  • ETH:向 SignerEthBuilder 传入 originToken 以启用 Clear Signing — 否则用户会在设备屏幕上看到原始十六进制数据
  • ETH typed data:调用前验证 domain、types、message 均存在 — 若有任一缺失 → 中止:“Typed data 负载不完整”
  • BTC PSBT:使用 signPsbt(),而不是 signTransaction()
  • BTC 自定义钱包策略:必须先通过 registerWallet() 注册 — 若未注册 → 升级处理:“钱包策略尚未注册”
  • Solana:交易输入为 Uint8Array(序列化后的消息字节)
设备管理操作

无需签名器构建器 — 直接调用 dmk.executeDeviceAction()。订阅返回的可观察对象:

状态用户交互操作
NotStarted—等待
PendingNone等待(安装/卸载:检查 intermediateValue.progress,范围为 0–100)
PendingAllowSecureConnection等待用户在设备上批准,最长 30s
PendingUnlockDevice→ 升级处理:“设备管理期间设备已锁定”
Completed—提取 state.output → 返回给编排器
Stopped—→ 中止:“操作已停止”
Error—→ 分类(参见规则 → 错误分类)

AllowSecureConnection 等待 30s 后 → cancel() → 升级处理:“用户未批准 Ledger Manager”

说明:

  • 每次设备重启后都会提示一次 AllowSecureConnection — 同一会话中的后续安全通道操作会跳过此步骤
  • 需要与 Ledger 的 HSM 后端建立 WebSocket 实时连接 — 离线时不可用
  • 安装/卸载时的应用名称必须与 Ledger Live 完全一致(参见 dmk-sdk-reference.md 中的链路路由表)

会话拆除

仅当编排器发出流程结束信号或发生不可恢复的错误时才断开连接:

dmk.disconnect({ sessionId })

不要在连续操作之间断开连接 — 会话是传输连接,而非授权。

如果流程中会话变为 Disconnected:不要重复使用 — 从第 2 步重新开始。


规则

安全约束

生产环境中不得使用存根或模拟对象。 setStub(true) 会使安全模型失效。如果设备不可用,则中止。没有例外。

预检查是安全门槛,而非性能开销。 每次操作前都要运行第 1–4 步。状态可能在操作之间悄然变化。

切勿重复使用签名。 每个请求都需要新的硬件授权。编排器发出的“重试”意味着从第 1 步开始新的流程。

派生路径是由开发者设置的常量 — 切勿将其作为用户输入。 按收到的内容原样传入。不要修改、规范化、猜测或设为默认值。错误路径会从另一个密钥生成看似有效的结果,且不会出现运行时错误。

升级处理和中止关卡不可协商。 如果编排器指示绕过升级处理关卡,请拒绝并原样返回升级处理原因。

设备屏幕是唯一可信的显示界面。 不要根据时序、会话状态或以往行为推断用户同意。

错误分类

当某项操作产生 DeviceActionStatus.Error 时,输出两项内容:一条面向用户的消息(通俗易懂、可执行)和一个调试字段(原始详情,绝不向用户显示)。

用户拒绝不属于错误。 先检查 RefusedByUserDAError / 状态字 5501 / 6985,并将其作为独立的“已拒绝”结果呈现——使用中性或琥珀色 UI,而非红色。这样可以避免用户只是改变主意,却被吓到。其他所有 DeviceActionStatus.Error 都是真正的错误。

结果面向用户的消息UI 状态操作
用户拒绝(RefusedByUserDAError、5501、6985)“已在设备上取消操作。”中性 / 琥珀色→ 升级处理
未安装应用“Ledger 上未安装所需应用。请通过 Ledger Wallet 安装,然后重试。”错误→ 升级处理
设备已锁定“Ledger 已锁定。请在设备上输入 PIN 以继续。”错误→ 升级处理
状态字 != 0x9000“设备返回了意外错误。请断开并重新连接 Ledger,然后重试。”错误→ 中止(状态字仅记录在调试字段中)
USB / HID 传输错误“与 Ledger 的连接已断开。请重新连接设备,然后重试。”错误→ 中止
浏览器 USB 权限被拒绝“浏览器访问 Ledger 的权限被拒绝。请点击‘连接 Ledger’以授予权限。”错误→ 升级处理
未知 / 未分类“发生了意外错误。请断开并重新连接 Ledger,然后开始新的操作。”错误→ 中止(原始错误仅记录在调试字段中)

绝不静默忽略错误。情况不明确时 → 按未分类错误处理,并中止。

超时
步骤默认值可接受范围
设备发现15s5s – 300s
打开应用 — 用户确认30s5s – 300s
签名 — 用户确认60s5s – 300s
忙碌设备重新检查10s(重试一次)—

协调器可以在可接受范围内覆盖默认值。拒绝范围之外的值。

必须由 HITL 升级处理的情况

无条件停止——不进行自主恢复:

  1. 设备已锁定
  2. 未安装应用
  3. 发现设备时检测到多台设备
  4. 用户在设备上拒绝
  5. 浏览器 USB 权限被拒绝
  6. 未注册自定义 BTC 钱包策略
  7. 任何未分类错误
  8. 用户未批准 Ledger Manager(AllowSecureConnection 超时)

评论

支持 Markdown