mcpField
D
dmk-business-logic

dmk-business-logic

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

关于 dmk-business-logic

为使用 Ledger Device Management Kit(DMK)的开发者提供参考,解释 API 设计概念、设备交互、传输限制、签名及安全相关行为。

主要功能

  1. 01清晰签名与盲签概念
  2. 02安全通道要求
  3. 03设备操作与命令
  4. 04会话生命周期与传输方式
  5. 05派生路径指导
  6. 06设备真伪检查

适用场景

  1. 01选择设备操作或命令
  2. 02设计交易签名流程
  3. 03管理 Ledger 连接会话
  4. 04设置链的派生路径

安装

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

$npx skills add https://github.com/ledgerhq/agent-skills --skill dmk-business-logic

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

详细介绍

DMK 业务逻辑与概念

本技能解释 DMK API 设计决策背后的原因——领域模型、安全限制和权衡取舍——帮助开发者理解其设计缘由,而不仅仅是调用方法。在实现过程中需要澄清某个术语或概念时,ledger-dmk-implementation/SKILL.md 也会将其作为连接器加载。


明文签名与盲签名

含义

盲签名是指用户在 Ledger 屏幕上看到原始十六进制字节——一长串无法阅读、无法验证的字符。用户需要批准一项自己无法有意义地审查的操作。

明文签名是指用户在设备屏幕上看到人类可读的交易详情——收款地址、金额、代币名称、合约名称、费用。按下按钮前,用户可以核实自己实际批准的内容。

重要性

设备屏幕是唯一可信的显示界面。被入侵的主机(恶意软件、钓鱼网站)可以在浏览器或桌面 UI 上向用户显示任何内容。设备屏幕无法伪造。明文签名让设备屏幕发挥作用,而盲签名则让它失去意义。

在 DMK 中的工作方式

即使没有明文签名,DMK 也能正常工作——明文签名是增强功能,并非前提条件。要为 Ethereum 启用明文签名:

  • @ledgerhq/context-module 无论如何都必须安装——它是 ETH 签名器工具包的强制同级依赖,负责获取设备显示人类可读字段所需的元数据(ABI、代币信息、NFT 详情)。
  • originToken 是传递给 SignerEthBuilder 的可选合作伙伴令牌。没有它,签名器仍可工作,但设备会显示原始十六进制内容——体验会悄然退化为盲签名,且不会出现运行时错误。要获取令牌,请加入 Ledger 合作伙伴计划:https://developers.ledger.com/docs/clear-signing/for-wallets。
// Clear Signing enabled (requires partner token):
new SignerEthBuilder({ dmk, sessionId, originToken: "your-partner-token" }).build();

// Blind signing — works but users see raw hex on device:
new SignerEthBuilder({ dmk, sessionId }).build();

对于 Bitcoin 和 Solana,明文签名由应用处理——无需 originToken,但设备上的 Ledger 应用必须支持相应的交易类型。

开发者检查清单
  • originToken 是可选的——可以先集成并发布,准备好在生产环境启用明文签名后,再加入 Ledger 合作伙伴计划
  • 使用 ETH 签名器工具包时,始终安装 @ledgerhq/context-module,开发期间也不例外
  • 对 getAddress() 流程始终使用 checkOnDevice: true——对于接收流程,这是与明文签名等效的地址验证方式

安全通道

定义

安全通道是 Ledger 设备与 Ledger 的 HSM(硬件安全模块)后端之间的加密、经身份验证的连接。它允许后端在设备上执行无法本地完成的特权操作。

哪些操作需要安全通道
操作是否需要安全通道
GenuineCheckDeviceAction是
ListInstalledAppsDeviceAction是
InstallAppDeviceAction是
UninstallAppDeviceAction是
所有签名器操作(签名、获取地址)否
OpenAppDeviceAction否
工作方式
  1. DMK 与 Ledger 的 HSM 建立 WebSocket 连接,地址为 wss://manager.live.ledger.com
  2. 设备与 HSM 执行双向身份验证握手
  3. 设备屏幕会提示用户执行 AllowSecureConnection——用户必须在设备上亲自批准连接
  4. 批准后,该会话在设备本次重启期间始终可信
实际影响
  • 需要互联网。 安全通道操作在离线状态下会失败——没有本地备用方案。

设备操作与命令

两级 API

DMK 提供两级设备交互方式:

命令(dmk.sendCommand())是底层的单次 APDU 往返操作。它们向设备发送一条指令,并同步返回结果。不处理任何用户交互——调用方需要负责其他所有事项。

设备操作(dmk.executeDeviceAction() 或签名器套件方法)是高级编排流程。它们通过单个可观察对象处理完整流程:检测解锁状态、打开应用、发出用户确认提示、重试以及发出终止状态。

何时使用哪种方式
使用场景使用方式
签署交易、获取地址签名器套件设备操作(通过签名器构建器)
真伪检查、安装/卸载应用使用相应的 DeviceAction 类调用 dmk.executeDeviceAction()
打开应用并显示用户确认界面通过 dmk.executeDeviceAction() 调用 OpenAppDeviceAction
检查固件版本、获取当前应用名称sendCommand()——操作简单,无需用户交互
自定义/不受支持的链、原始 APDU使用 ApduBuilder 调用 sendCommand()——仅在没有签名器套件时使用
设备操作的作用

如果没有设备操作,每位开发者都必须重新实现以下功能:

  • 检测并等待设备解锁
  • 检测并切换当前活动应用
  • 处理 ConfirmOpenApp 提示
  • 将状态字错误映射为面向用户的消息
  • 管理超时和取消

设备操作封装了所有这些功能。它们返回的可观察对象会发出可直接对应到 UI 提示的状态——UserInteractionRequired.SignTransaction 表示“向用户显示提示”,DeviceActionStatus.Completed 表示“已完成,提取输出”。


会话和 SessionId

什么是会话

会话表示与特定 Ledger 设备之间的活动 USB/BLE 连接。它由 dmk.connect() 创建,并由 dmk.disconnect() 销毁。sessionId 是一个不透明字符串,用于在 DMK 实例中标识会话。

什么不是会话
  • 它不是按链区分的。相同的 sessionId 可用于 ETH、BTC、SOL 以及任何其他签名器,无需重新连接。
  • 它不是授权。设备仍会针对每次签名操作提示用户——会话纯粹是一个传输句柄。
  • 它不会在页面加载之间持久保留。刷新浏览器会销毁会话。
会话生命周期

会话在以下情况下有效:

  • 调用 dmk.disconnect({ sessionId })
  • 拔下 USB 线缆(会话状态变为 Disconnected)
  • 关闭浏览器标签页

不要尝试使用现有的 sessionId 重新连接——一旦变为 Disconnected,就从 startDiscovering() 开始新的流程。

会话刷新器

DMK 会定期轮询设备,以更新会话状态(当前应用、设备状态)。这就是会话刷新器。在多个标签页共享同一台实体设备的场景中,请禁用它,以避免轮询冲突:

dmk.connect({ device, sessionRefresherOptions: { isRefresherDisabled: true } });

传输

抽象的内容

传输层处理主机与 Ledger 设备之间的物理通信协议。无论使用哪种传输方式,DMK 的 API 都相同——只有初始化方式不同。

传输方式协议环境
WebHIDUSB HID,64 字节帧浏览器(仅限 Chromium)
WebBLEBluetooth GATT浏览器
Node-HID通过原生插件使用 USB HIDNode.js、Electron
React Native HIDUSB HIDReact Native
React Native BLEBluetoothReact Native
Speculos连接模拟器的 TCP 套接字仅限开发/CI
浏览器限制

WebHID 要求:

  • 基于 Chromium 的浏览器(Chrome、Edge、Brave)——Firefox 和 Safari 不支持 WebHID
  • HTTPS 或 localhost——WebHID 在普通 HTTP 上会被阻止
  • 用户操作——必须通过按钮点击或等效操作调用 startDiscovering() 和 connect()。如果在页面加载时调用,则会静默失败。
每个 DMK 实例使用一种传输方式

每个 DeviceManagementKitBuilder 接受一种或多种传输方式。实际使用中,请使用一种。DMK 会按注册顺序尝试传输方式。


派生路径

定义

派生路径是一系列索引,用于指定从设备上存储的根种子派生哪个密钥。给定相同的助记词,相同的路径始终会生成相同的密钥;不同的路径则会生成完全不同的密钥,且不会出现运行时错误。

为什么它们是开发者常量,而不是用户输入

从设备的角度看,不存在“错误路径”——每条路径都会生成有效密钥。如果用户输入的路径哪怕只有一个片段不同,得到的地址也会不同。发送到该地址的资金将无法访问,除非知道正确的路径。这是一个悄无声息且无法挽回的错误。

路径必须在应用代码中硬编码为常量,并与用户钱包采用的标准一致。

路径格式规则
  • 不要添加 m/ 前缀。 DerivationPathUtils.splitPath 会解析由 / 分隔的片段。开头的 m 不是有效片段——parseInt("m") 会返回 NaN 并抛出“提供了无效数字”错误。请使用 "44'/60'/0'/0/0",而不是 "m/44'/60'/0'/0/0"。
  • 强化片段使用 ' 后缀(例如 44')。这是在索引上加上 0x80000000 的简写形式。
  • 账户和索引是不同的概念。account 用于选择钱包(大多数用户使用 0)。index 用于选择该钱包中的地址。
各链的标准路径
链Ledger Live 路径备注
Ethereum44'/60'/0'/0/0BIP44,账户 0,索引 0
Bitcoin Native SegWit84'/0'/0'BIP84,传递给钱包策略
Solana44'/501'/0'/0'社区标准
Cosmos44'/118'/0'/0/0BIP44

对于未列出的链:SLIP-0044 定义了币种类型(github.com/satoshilabs/slips/blob/master/slip-0044.md)。


BOLOS

BOLOS(Blockchain Open Ledger Operating System),现称为 Ledger OS,是 Ledger 设备的操作系统。当没有应用打开且设备处于主屏幕(仪表板)时,state.currentApp.name 会返回 "BOLOS"。

以下是检测当前没有应用打开的方法:

const isOnDashboard =
  state.currentApp.name === "BOLOS" || state.currentApp.name === "Dashboard";

使用 signer kit 设备操作时,无需显式检测这一状态——它们会自动处理应用切换。此检测适用于操作前的 UX 提示(“当前没有应用打开,继续后将打开正确的应用”)。


真伪验证

真伪验证用于确认实体 Ledger 设备是 Ledger 制造的正版硬件,而非仿冒品。设备会证明其持有私钥,该私钥对应的证书由 Ledger 的根 CA 签名,并通过 Secure Channel 验证。

它会返回 output.isGenuine: boolean。

使用时机: 在继续操作前必须确认设备真伪的高安全性流程中,例如企业密钥管理设置或首次设备接入流程。常规签名操作不需要进行真伪验证。

无法证明的事项: 它无法证明设备在制造后未遭篡改,也无法证明助记词已正确备份。


Ledger Wallet / Ledger Live

Ledger Live 是 Ledger Wallet 的旧称——两者指的是同一个桌面和移动应用。文档、技能文件和 SDK 参考资料可能会使用其中任一名称;请将它们视为相同名称。

设备操作中使用的应用名称(OpenAppDeviceAction、InstallAppDeviceAction、UninstallAppDeviceAction)必须与 Ledger 应用目录中的名称完全一致——也就是 Ledger Wallet 中显示的名称。拼写或大小写有误会导致静默失败,或出现无法说明具体原因的晦涩错误。

评论

支持 Markdown