标识符(Identifiers)
searchDevices、getFeatures、getPassphraseState 以及各链方法的响应里,
会出现若干个看起来都像”ID”的字段。这一页作为唯一权威参考,说明每个字段
到底代表什么、何时变化、在不同传输方式下格式差异是什么。
找的是传入 SDK 的参数(
passphraseState、initSession、useEmptyPassphrase等)?请看 通用参数。
四层标识符
每个标识符属于四类生命周期之一。知道它属于哪一类,就知道什么时候该刷新、什么 时候能长期缓存。
| 层级 | 生命周期 | 变化触发 | 字段 |
|---|---|---|---|
| 物理硬件 | 永久(跟硬件本体绑定) | 永不变化 | uuid、onekey_serial、serial_no |
| 传输连接 | 本次连接 | 重新 searchDevices();换传输方式 | connectId、path、name、deviceType |
| 种子 / 钱包状态 | 恢复出厂 / 擦除 / 恢复助记词之前 | 恢复出厂、重新导入助记词、擦除 | device_id / deviceId、label |
| 会话 | 设备锁屏之前 | 自动锁屏、手动锁、USB 断开 | session_id、passphraseState |
哪些 ID 需要你传进去?
上面列的字段中只有 3 个 是你调用 SDK 时需要传进去的入参,其他全部只在响应里读。
| ID | 需要传入? | 传在哪里 | 什么时候必传? |
|---|---|---|---|
connectId | ✅ | 每个方法的第一个位置参数 | 总是必传 |
deviceId | ✅ | 签名 / 地址 / 加密类方法的第二个位置参数 | 钱包级操作必传;设备管理操作可省 |
passphraseState | ✅ | 在 params 对象里 | 只在访问隐藏钱包(带 passphrase)时传 |
uuid、onekey_serial、device_id、session_id、path、name、deviceType、label | ❌ 仅响应字段 | — | — |
调用形态
// 设备级 —— 只要 connectId
HardwareSDK.getFeatures(connectId);
HardwareSDK.deviceLock(connectId, {});
HardwareSDK.getPassphraseState(connectId, { initSession: true });
// 钱包级(标准钱包)—— connectId + deviceId
HardwareSDK.evmGetAddress(connectId, deviceId, {
path: "m/44'/60'/0'/0/0",
useEmptyPassphrase: true,
});
// 钱包级(隐藏钱包)—— connectId + deviceId + passphraseState
HardwareSDK.evmSignTransaction(connectId, deviceId, {
path: "m/44'/60'/0'/0/0",
transaction: { /* ... */ },
passphraseState, // 由 getPassphraseState 一次性获取
});各方法的 ID 要求
| 类别 | 适用场景 | 代表方法 |
|---|---|---|
🟡 仅 connectId | 设备级操作(不触碰钱包状态) | searchDevices · getFeatures · getPassphraseState · deviceLock · deviceUnlock · deviceWipe · deviceSettings · deviceVerify · cancel · checkFirmwareRelease · checkBootloaderRelease |
🔵 connectId + deviceId | 钱包级:地址派生 / 签名 / 加密 | evmGetAddress · evmSignTransaction · evmSignMessage · btcGetAddress · btcSignTransaction · btcSignPsbt · solGetAddress · solSignMessage · nostrEncryptMessage · allNetworkGetAddress · 所有其他链方法 |
🟣 connectId + deviceId + passphraseState | 和 🔵 相同,但访问的是带 passphrase 的隐藏钱包 | 🔵 里所有方法,params 里带非空 passphraseState |
漏传 / 传错的后果
| 漏传 / 传错 | SDK 行为 |
|---|---|
connectId 缺失或未知 | DeviceNotFound —— SDK 不知道要路由到哪台设备 |
deviceId 不对(中途换了种子) | DeviceCheckDeviceIdError —— SDK 拒绝在另一个种子上签名 |
访问隐藏钱包漏传 passphraseState | ⚠️ 返回标准钱包的结果,无任何报错 —— 地址 / 签名都是另一个钱包的 |
passphraseState 不匹配当前 session | 错误码 112(passphrase state mismatch)—— session 过期或隐藏钱包变了 |
passphraseState 和 useEmptyPassphrase: true 同时传 | passphraseState 优先(走隐藏钱包)——useEmptyPassphrase 被忽略 |
⚠️ 第三行是最坑的:隐藏钱包调用时漏传
passphraseState,拿到的是标准钱包的地址/签名,完全没有报错。所以隐藏钱包场景里,getPassphraseState拿一次passphraseState之后必须挂到后续所有钱包级调用上;如果明确就是要走标准钱包,就显式传useEmptyPassphrase: true,别把它留空。
物理硬件标识符
不可变值,标识物理设备本体。重置、换种子、升级固件后都不变。
| 字段 | 来源 | 格式 | 说明 |
|---|---|---|---|
uuid | searchDevices()[].uuid | 依传输方式(见下) | USB 传输时和 connectId 相同。BLE 上可能和 OS 层的 connectId 不同。 |
onekey_serial / onekey_serial_no | getFeatures().payload | CLB21J0013 这种格式 | 出厂分配;印在设备 / 包装盒上。 |
传输连接标识符
标识一次具体连接。同一台物理设备在 USB 和 BLE 下的 connectId 不一样,
不能互换使用。
connectId —— 路由用的 key
每次调用 SDK 方法都要把 connectId 作为第一个参数,SDK 据此判断请求发给哪台
设备 / 哪个连接。同传输下的多次 searchDevices() 返回相同值。
| 传输方式 | connectId 格式 | 例子 |
|---|---|---|
| WebUSB | 设备序列号 | PRC10J0017A |
| Bridge | 设备序列号 | PRC10J0017A |
| node-usb (CLI) | 设备序列号 | CLB21J0013 |
| Android BLE | MAC 地址 | AA:BB:CC:DD:EE:FF |
| iOS BLE | CoreBluetooth UUID | XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX |
| Desktop BLE(Electron/Noble,macOS) | 32 位小写十六进制 UUID | 1f6dad0b8782aab31d2f7ae2b11e5b6c |
| Desktop BLE(Electron/Noble,Windows) | 12 位小写十六进制 MAC(无冒号) | e4e65539cf33 |
| Desktop BLE(Electron/Noble,Linux) | MAC 地址 | AA:BB:CC:DD:EE:FF |
⚠️ 如果你的应用同时支持 USB 和 BLE 连同一台设备,必须按传输分别缓存
connectId,两套值不能互用。
其他传输层字段
| 字段 | 作用 | 典型值 | 说明 |
|---|---|---|---|
path | 底层总线路径 | USB: 设备路径或 device_id;BLE: undefined | 实现细节 —— 调用路由请始终用 connectId,不要用 path。 |
name | 展示用的人类可读标签 | USB: 设备 label;BLE: 广播名 | 仅用于 UI 展示,不参与路由。 |
deviceType | 设备型号 | classic / classic1s / classicpure / mini / touch / pro | 用于按型号分支能力(如按键机型才走 PIN matrix 流程)。取值来自 EDeviceType。 |
种子 / 钱包状态标识符
deviceId(searchDevices 响应里)和 device_id(getFeatures 响应里)
是同一个值,表示设备上当前加载的种子。
deviceId 会变 | deviceId 不变 |
|---|---|
| 恢复出厂 | 重启 |
| 恢复助记词(换种子) | 锁 / 解锁 |
| ”Wipe” + 重新初始化 | 重新插拔 USB |
| 在测试 / 正式种子间切换(开发机) | 改 passphrase |
用法
const { payload: features } = await HardwareSDK.getFeatures(connectId);
const deviceId = features.device_id;
// 每次签名调用都带上 deviceId —— SDK 用它检测过程中种子是否变了,
// 变了就抛 `DeviceCheckDeviceIdError` 阻止签在错的种子上
await HardwareSDK.evmSignTransaction(connectId, deviceId, { ... });遇到 DeviceCheckDeviceIdError 就重新 getFeatures(connectId) 并更新缓存
的 deviceId。
会话标识符
两个会话层字段名字类似但作用不同。
session_id —— 短期会话 token
设备初始化 passphrase session 时临时生成的随机 token。
getPassphraseState 或任何触发 session 初始化的调用之后,会出现在
features.session_id 里。
- 锁屏即失效(自动锁、手动锁、USB 断开)。
- SDK 内部用它维持设备端缓存的 passphrase。
- 一般不直接暴露给应用代码 —— 大多数应用只需要
passphraseState。
passphraseState —— 隐藏钱包标识
和某个 passphrase 绑定的确定性隐藏钱包标识。getPassphraseState() 返
回。同一个种子 + 同一个 passphrase 永远产生同一个 passphraseState,
所以你可以用它来判断”这是不是同一个之前看到过的隐藏钱包”,而不必保存
passphrase 本身。
- 作为
passphraseState通用参数传给后续所有需要绑在这个隐藏钱包上的 SDK 调用。 - 跨进程复用:持久化
(deviceId, passphraseState, session_id)三元组,进程 启动时调preloadSessionCache恢复 session。 - 清掉缓存的
passphraseState不会让隐藏钱包失效 —— 用户再输一次同样的 passphrase 就能复现出相同的钱包。
session_id | passphraseState | |
|---|---|---|
| 生命周期 | 锁屏前 | 事实上永久(passphrase 不变就不变) |
| 是否确定性 | 每次会话随机 | 按 passphrase 确定性 |
| 角色 | 保持设备侧 session 有效 | 指明”是哪一个隐藏钱包” |
实例拼装
通过 USB(node-usb 传输)连接 Classic 1S 时,searchDevices() 返回:
{
"connectId": "CLB21J0013", // 传输层(USB 下 = 设备序列号)
"uuid": "CLB21J0013", // 物理层(USB 下 = connectId)
"deviceType": "classic1s", // 传输层
"deviceId": "399A2470958EDB3D9F3826C2", // 种子状态;重置后会变
"path": "399A2470958EDB3D9F3826C2", // 传输内部;各传输不一样
"name": "OneKey Classic 1S" // 展示标签
}继续调 getFeatures(connectId) 会拿到:
{
"device_id": "399A2470958EDB3D9F3826C2", // 和上面 deviceId 相同
"onekey_serial": "CLB21J0013", // 物理;USB 下和 connectId 相同
"session_id": "80cb8aef933870e4…", // 短期;锁屏后重置
"passphrase_protection": true,
"unlocked": true,
"label": "OneKey Classic 1S"
}用户输完 passphrase 后,getPassphraseState(connectId) 返回:
{
"success": true,
"payload": "abc123…" // passphraseState —— 后续调用带上它
}常见混淆
connectId vs uuid
USB 下两者是同一个字符串(都是设备序列号)。BLE 下可能不一样:
connectId 是 OS 层的连接句柄(MAC / CoreBluetooth UUID / …),uuid 则是
SDK 层暴露给应用用的稳定 ID。路由始终用 connectId;如果需要一个跨传输
稳定的 ID 做展示用途,再考虑 uuid。
deviceId vs uuid / onekey_serial
deviceId—— 重置 / 换种子后会变。用来回答*“这还是同一个钱包吗?”*uuid/onekey_serial—— 永不变化。用来回答*“这还是同一台物理设备 吗?“*
session_id vs passphraseState
session_id锁屏即失效;passphraseState不会。passphraseState标识是哪一个隐藏钱包;session_id标识这条还活着 的会话。- 跨调用复用会话就一起持久化
(passphraseState, session_id);如果两次调用 之间设备锁屏了,就丢掉缓存的session_id、强制重新解锁。
device_id(蛇形)vs deviceId(驼峰)
同一个值,两种上下文:
device_id出现在getFeatures().payload(固件层,蛇形命名)。deviceId出现在searchDevices()[]里以及大多数 SDK 方法的第二个位置参 数(JS 层,驼峰命名)。
参考
- 通用参数 —— 传进 SDK 的参数
- Passphrase —— 隐藏钱包流程
- PIN 码 —— PIN 输入流程
- Search Devices —— 返回
connectId、uuid、deviceType、deviceId - Get Features —— 返回
device_id、session_id、onekey_serial等