跳到主要内容

核心接口说明

这里汇总 UKey Wallet Hardware SDK 的通用调用方式。你可以从这里了解设备标识如何获取、请求如何串行执行、UI 事件如何响应,以及不同链接口在参数和错误处理上的共性要求。

速览流程

  • 调用形式:示例里通常把 SDK 入口命名为 ukeySdk,因此调用会写成 ukeySdk.method(connectId, deviceId?, params),返回 Promise<{ success, payload }>;读取 payload 前先确认 success
  • 设备标识connectId 来自 searchDevices,用于定位连接;deviceId 来自 getFeatures,用于确认当前钱包状态。BLE 场景通常必须传入 deviceId,WebUSB 场景也建议携带。
  • 交互事件:应用入口订阅一次 UI_EVENT 即可。只有 PIN、Passphrase、Bootloader 设备选择等需要用户输入的事件才调用 uiResponse
  • 链接校验:HD Path 按链校验;隐藏钱包场景使用 initSession + passphraseState;同一设备上的请求保持串行,避免传输层互相抢占。
const opResult = await ukeySdk.evmGetAddress(connectId, deviceId, {
path: "m/44'/60'/4'/0/1",
});

if (!opResult.success) throw new Error(opResult.payload.error);
console.log(opResult.payload.address);

交互图示

硬件 SDK 请求/响应流程图

核心标识环境

名称用途来源说明
connectId连接标识,用来把请求路由到具体设备searchDevices()同一设备通常保持稳定;WebUSB/Bridge 多数情况下对应序列号;BLE 使用系统层标识(Android MAC / iOS UUID)。
deviceId当前钱包状态标识getFeatures(connectId)设备重置、擦除、恢复或更换种子后会变化;敏感操作会借此避免请求发到错误钱包。
  • 建议把 connectIddeviceId 成对缓存;出现 DeviceCheckDeviceIdError、用户恢复设备或切换设备时,重新调用 getFeatures
  • SDK 相关包需要版本一致:@ukeyfe/hardware-common-connect-sdk@ukeyfe/hardware-core@ukeyfe/hardware-shared 应与固件和 Bridge 能力保持匹配。
  • WebUSB 需要 HTTPS 和用户手势;React Native BLE 需要蓝牙及平台权限;lowlevel 环境需要宿主自行实现 64 字节帧收发。
  • Bootloader 模式下只有部分固件接口可用;使用 Bridge 时请确认 Bridge 正在运行且端口未被其他程序占用。

接口标识要求

标识组合用途说明常见接口
🟢 无需标识SDK 初始化、配置、事件管理init on/off searchDevices getLogs dispose uiResponse
🟡 仅需 connectId设备管理、状态查询、固件操作getFeatures getPassphraseState cancel deviceSettings deviceReset
🔵 需要 connectId + deviceId区块链签名、地址派生、加解密evmSignTransaction btcSignTransaction solanaSignMessage allNetworkGetAddress

建议调用顺序

建议按固定顺序组织请求:初始化 SDK搜索设备读取设备信息订阅 UI 事件执行具体操作释放或清理资源

import ukeySdk, {
UI_EVENT,
UI_REQUEST,
UI_RESPONSE,
} from "@ukeyfe/hardware-common-connect-sdk";

// 1. 先初始化 SDK(应用入口跑一次就够)
await ukeySdk.init({ env: "webusb", fetchConfig: true, debug: false });

// 2. 搜索当前已经连上的设备
const availableDevices = await ukeySdk.searchDevices();
if (!availableDevices.length) throw new Error("No device");
const [{ connectId }] = availableDevices;

// 3. 读取设备信息(BLE 必做,WebUSB 建议做)
const featureInfo = await ukeySdk.getFeatures(connectId);
const deviceId = featureInfo?.payload?.device_id;

// 4. 监听 UI 事件
ukeySdk.on(UI_REQUEST.REQUEST_PIN, () => {
// 拉起 PIN 输入界面,拿到输入后再调用 uiResponse
});
ukeySdk.on(UI_REQUEST.REQUEST_PASSPHRASE, () => {
// 拉起 Passphrase 输入界面
});

// 5. 执行链上操作(这里以 EVM 签名举例)
await ukeySdk.evmSignTransaction(connectId, deviceId, {
path: "m/44'/60'/4'/0/1",
});

调用提醒:面向同一台设备时,把硬件请求排队执行;用户切到另一台设备后,先重新读取一次 getFeatures;页面销毁前记得解绑事件监听;只有确实要重置传输上下文或结束 SDK 会话时,才调用 ukeySdk.dispose()

参数说明

常见入参(CommonParams)

字段用途说明典型场景
initSession?: boolean主动建立硬件会话,可配合 Passphrase 状态使用首次操作前预热会话,减少后续交互
passphraseState?: string隐藏钱包会话标识连续使用同一个隐藏钱包时携带
useEmptyPassphrase?: boolean强制使用标准钱包避免误进入隐藏钱包
deriveCardano?: boolean提前派生 Cardano 相关数据会话内首次 Cardano 操作
retryCount? / pollIntervalTime? / timeout?调整轮询与超时策略BLE 或网络状态不稳定时
detectBootloaderDevice?: boolean检测到 Bootloader 设备时快速返回引导用户退出 Bootloader
skipWebDevicePrompt?: boolean跳过 WebUSB 选择弹窗复用已经授权的 WebUSB 设备
keepSession?已不建议继续使用优先改用会话和 Passphrase 状态

组合参考片段:

// 隐藏钱包并连续调用,避免反复弹提示
const sessionOptions = {
initSession: true,
keepSession: true,
passphraseState: "hidden-wallet-id",
};

await ukeySdk.evmSignMessage(connectId, deviceId, {
path: "m/44'/60'/4'/0/1",
messageHex,
...sessionOptions,
});

传输方式差异

传输方式典型入口主要差异适合场景
WebUSBenv: "webusb" + @ukeyfe/hardware-common-connect-sdk纯浏览器接入,不需要原生桥接;依赖 HTTPS 和用户手势Web 站点、后台控制台、浏览器 DApp
React Native BLEenv: "react-native" + @ukeyfe/hardware-ble-sdk + @ukeyfe/hardware-transport-react-native需要 BLE 原生模块和平台权限;由 RN 侧负责扫描、连接和收发纯 React Native App
iOS 原生低层接入env: "lowlevel" + WKWebViewJavascriptBridge + CoreBluetoothJS 运行在 WebView,BLE 由原生侧处理,再通过桥接回传iOS 原生壳 + Web 业务层
Android 原生低层接入env: "lowlevel" + WebView + JSBridge + Nordic BLEJS 同样保留在 WebView,Android 侧负责配对、连接、通知和回传Android 原生壳 + Web 业务层

这些方式的链 API 调用形状是一样的,差别主要在初始化方式、权限要求和底层传输实现。

常见组合

  • Web 站点 + WebUSB:最轻量,适合浏览器直连设备。
  • React Native App + BLE:适合纯 RN 项目,需要本地 BLE 能力。
  • iOS 原生壳 + WebView + CoreBluetooth:适合保留 Web 业务层,同时由原生侧接管 BLE。
  • Android 原生壳 + WebView + Nordic BLE:与 iOS 方案类似,适合原生容器承载 Web 页面。
  • 隐藏钱包连续操作 + 任意传输方式:建议配合 initSession + passphraseState,减少重复确认。

代码示例

// WebUSB
await ukeySdk.init({ env: "webusb", fetchConfig: true, debug: false });

// React Native BLE
await ukeySdk.init({ env: "react-native", fetchConfig: true, debug: __DEV__ });

// iOS / Android 原生低层接入
await ukeySdk.init({ env: "lowlevel", debug: true });

HD Path 规则

path 支持字符串或数组形式:path: string | number[]。大多数链遵循 BIP44 思路,不同曲线对路径硬化要求不同;例如 Solana、NEAR 等 ed25519 链通常需要全硬化路径。

路径速查

  • EVMm/44'/60'/6'/0/2,标准 EVM 账户最常用。
  • BTC (Nested SegWit)m/49'/0'/0'/0/0;如果是 Native SegWit,通常会走 84'
  • Solanam/44'/501'/3'/0',这类 ed25519 链一般要求全硬化。
  • NEARm/44'/397'/0'/0'/1',同样属于全硬化路径。
  • Cardanom/1852'/1815'/1'/0/1,质押相关路径常见为 .../2/0
  • TRONm/44'/195'/1'/0/1,路径风格和 EVM 比较接近。

如果改用数组传路径,硬化层级需要带上 0x80000000 标记,例如:[(44 | 0x80000000) >>> 0, (0 | 0x80000000) >>> 0, 0x80000000, 0, 0]

如果设备返回 "forbidden path",通常是路径长度、coin type 或硬化标记不符合该链要求。请以对应链 API 页面中的路径规则为准。

事件说明

SDK 会通过事件把设备状态和用户交互需求传给应用,常用通道如下:

事件通道说明
UI_EVENT用户交互提示(PIN、Passphrase 等)
DEVICE_EVENT设备状态变化(连接、断开、能力更新等)
FIRMWARE_EVENT固件升级信息

只有需要应用回传输入内容的 UI_REQUEST 才调用 uiResponse。纯提示类事件用于更新界面即可。多设备场景下,请根据事件中的设备标识把提示路由到对应设备。

需回传的 UI 请求

请求类别触发时机返回结果
REQUEST_PIN受保护调用且设备被锁定UI_RESPONSE.RECEIVE_PIN(软件盲输或硬件端输入)
REQUEST_PASSPHRASE软件输入隐藏钱包口令UI_RESPONSE.RECEIVE_PASSPHRASEvaluepassphraseOnDeviceattachPinOnDevicesave
REQUEST_PASSPHRASE_ON_DEVICE隐藏钱包口令交由硬件端输入UI_RESPONSE.RECEIVE_PASSPHRASEpassphraseOnDevice: true
REQUEST_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICEWeb Bootloader 设备选择UI_RESPONSE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICEdeviceId

展示类 UI 请求

请求类别用途
REQUEST_BUTTON在设备上提示确认
DEVICE_PROGRESS长任务进度
FIRMWARE_PROCESSING / FIRMWARE_PROGRESS / FIRMWARE_TIP固件升级或处理状态
BLUETOOTH_PERMISSION / LOCATION_PERMISSIONBLE 权限提醒
BOOTLOADER / REQUIRE_MODE / NOT_INITIALIZE / FIRMWARE_NOT_SUPPORTED模式/支持性提示

关键设备/固件事件

设备状态

  • CONNECT:设备接入且可用,刷新设备列表并自动选中。
  • DISCONNECT:设备拔出或 BLE 断开,标记会话失效并提示重新连接。
  • ACQUIRE:传输会话开始,阻塞并发请求并标记设备忙。
  • RELEASE:传输会话结束,放行队列中的下一个请求。
  • CHANGED:功能状态变更(如解锁后),重新执行 getFeatures 刷新缓存的 deviceId
  • USED_ELSEWHERE:发现传输冲突,提示关闭其他应用/Bridge。
  • UNREADABLE:权限或驱动异常,提示重新授权或检查驱动。

交互请求

  • BUTTON:设备等待确认,UI 显示“请在设备确认”。
  • PIN:设备等待 PIN,继续 PIN 输入流程。
  • PASSPHRASE:设备等待软件口令,继续口令输入流程。
  • PASSPHRASE_ON_DEVICE:设备等待在机输入口令,提示用户在设备上输入。
  • SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE:Bootloader 设备选择中,保持设备选择界面直至完成。

固件消息

  • FEATURES:能力快照,用于缓存能力信息。
  • SUPPORT_FEATURES:支持矩阵快照,用于缓存支持情况。
  • RELEASE_INFO:新固件信息,在安全时机提示升级。
  • BLE_RELEASE_INFO:新 BLE 固件信息,在安全时机提示升级。

事件处理范例

import ukeySdk, {
UI_EVENT,
UI_REQUEST,
UI_RESPONSE,
} from "@ukeyfe/hardware-common-connect-sdk";

const routeUiRequest = (uiEvent: any) => {
switch (uiEvent.type) {
case UI_REQUEST.REQUEST_PIN:
promptForPin(({ value }) =>
ukeySdk.uiResponse({
type: UI_RESPONSE.RECEIVE_PIN,
payload: value,
}),
);
return;
case UI_REQUEST.REQUEST_PASSPHRASE:
promptForPassphrase(({ value, onDevice, save }) =>
ukeySdk.uiResponse({
type: UI_RESPONSE.RECEIVE_PASSPHRASE,
payload: {
value,
passphraseOnDevice: onDevice,
attachPinOnDevice: false,
save,
},
}),
);
return;
case UI_REQUEST.REQUEST_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE:
presentDeviceChoices((deviceId) =>
ukeySdk.uiResponse({
type: UI_RESPONSE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE,
payload: { deviceId },
}),
);
return;
default:
console.log("收到的 UI 事件", uiEvent.type, uiEvent.payload);
}
};

ukeySdk.on(UI_EVENT, routeUiRequest);

输入安全

PIN 输入

  • UKey Core 26:仅支持设备端输入
  • UKey Lite 24 / Lite 25:支持盲输模式,但建议优先使用设备端输入
const PIN_KEYPAD_MAP = ["7", "8", "9", "4", "5", "6", "1", "2", "3"];
const keypadSlot = 1;

ukeySdk.uiResponse({
type: UI_RESPONSE.RECEIVE_PIN,
payload: PIN_KEYPAD_MAP[keypadSlot - 1],
});

Passphrase 输入

  • 标准钱包:等同于空口令路径,通常是默认选择。
  • 隐藏钱包:需要输入非空口令,且大小写会影响结果。
输入方案传参安全说明
硬件端完成(优先采用)passphraseOnDevice: true口令不经过应用侧,安全性最高
软件端输入{ value, passphraseOnDevice: false, save: true }仅在当前会话内使用,勿持久化明文
强制标准钱包useEmptyPassphrase: true明确不进入隐藏钱包

异常处理

错误分组典型原因建议
Device (101–118, 200)模式错误、设备忙、device_id 不匹配、未初始化先把设备切回正确模式,再重连并重试 init + getFeatures
IFrame (300–305)未 init、加载/超时/被拦截确保 init 成功且未被 CSP/istack 阻挡
Method/Firmware (400–418)入参错误、需固件升级、禁用路径说明校验入参/HD Path,提示升级固件
Transport (600–603)传输未配置、并发调用、protobuf 错误核验 env/Bridge,串行调用,对齐 SDK 版本要求
Bluetooth (700–722)扫描/权限/连接/超时核验蓝牙/定位权限与电量距离,重试连接
Runtime/Bridge (800–821)PIN/动作被取消、Bridge 权限/超时、盲签关闭重试或提示安装/启动 Bridge,确保签名模式
Web device (901–902)WebUSB/蓝牙授权缺失,或选择弹窗未能拉起重新请求授权,并确认 HTTPS 与用户手势条件满足

完整错误定义和 payload 结构可参考 HardwareError.ts

处理建议:在应用内维护错误码到用户提示的映射表,并提供重试、检查设备、升级固件等明确操作,避免只显示底层错误文本。

继续阅读

  • 传输适配 - WebUSB、React Native BLE、iOS/Android 底层接入
  • 链 API - 地址派生、消息签名、交易签名等链级接口
  • 迁移指南 - 从旧 Bridge 接入迁移到 common-connect