跳到主要内容

迁到 Common-Connect-Sdk

如果项目准备脱离旧 Bridge 通道,并把 SDK 入口换成 @ukeyfe/hardware-common-connect-sdk,可以按这里的步骤迁移。完成后,浏览器会直接通过 WebUSB 与 UKey Wallet 通信,不再经过 iframe Bridge。


前提

  • 请使用基于 Chromium 的桌面浏览器,例如 Chrome 或 Edge。
  • Node.js 建议 18 及以上,最好直接使用 LTS 版本。

改动点

  • SDK 入口从 @ukeyfe/hardware-web-sdk 切换为 @ukeyfe/hardware-common-connect-sdk
  • 初始化环境改为 env: 'webusb',不再配置 connectSrc
  • USB 授权必须由用户手势触发,并通过 UKEY_WEBUSB_FILTER 打开浏览器设备选择器。
  • PIN、Passphrase、设备插拔等交互统一通过 @ukeyfe/hardware-coreUI_EVENT / DEVICE 事件处理。
  • 删除 Bridge 专属检查,例如 checkBridgeStatus()、Bridge 安装提示和重启提示。
  • 大部分业务 API 名称保持不变,例如 searchDevicesgetFeaturesbtcGetAddress

部署

npm i @ukeyfe/hardware-common-connect-sdk @ukeyfe/hardware-core @ukeyfe/hardware-shared

初始化Common

import ukeySdk from "@ukeyfe/hardware-common-connect-sdk";

await ukeySdk.init({
env: "webusb",
debug: process.env.NODE_ENV !== "production",
fetchConfig: true,
});
  • hardware-common-connect-sdk 直接走 WebUSB,不依赖 iframe,因此不需要 connectSrc
  • 建议保留 fetchConfig: true,让 SDK 拉取设备能力和提示配置。

注册 UI 与设备事件处理(PIN / Passphrase / 插拔)

import { UI_EVENT, UI_REQUEST, UI_RESPONSE, DEVICE } from "@ukeyfe/hardware-core";

function bindDeviceEventHandlers() {
ukeySdk.on(UI_EVENT, async (message: any) => {
switch (message.type) {
case UI_REQUEST.REQUEST_PIN: {
// 正式环境请换成你自己的 PIN 输入界面
await ukeySdk.uiResponse({
type: UI_RESPONSE.RECEIVE_PIN,
// 优先让 PIN 在设备上输入(安全性更高)
payload: "@@UKEY_INPUT_PIN_IN_DEVICE",
});
break;
}

case UI_REQUEST.REQUEST_PASSPHRASE: {
// 正式环境请替换成你的 Passphrase 输入界面(设备端或软件端均可)
await ukeySdk.uiResponse({
type: UI_RESPONSE.RECEIVE_PASSPHRASE,
payload: { passphraseOnDevice: true, value: "" },
});
break;
}

default:
break;
}
});

ukeySdk.on(DEVICE.CONNECT, (payload: any) => {
console.log("收到设备连接事件:", payload);
});
ukeySdk.on(DEVICE.DISCONNECT, (payload: any) => {
console.log("收到设备断开事件:", payload);
});
}

bindDeviceEventHandlers();
  • 请及时订阅 UI_EVENT,否则 PIN、Passphrase 或确认事件无人响应时,请求会停在等待状态。
  • 具体详细参考:事件说明

申请USB权限

import { UKEY_WEBUSB_FILTER } from "@ukeyfe/hardware-shared";

// 放在按钮点击等明确用户动作里执行;静默弹出的 USB 授权会被浏览器拦截。
await navigator.usb.requestDevice({ filters: UKEY_WEBUSB_FILTER });

枚举设备并发起首次请求

// 1) 扫描设备
const deviceList = await ukeySdk.searchDevices();
if (!deviceList.success) throw new Error(deviceList.payload.error);
const { connectId, deviceId } = deviceList.payload[0] ?? {};

// 2) (按需执行)再向设备读取一次特征信息,优先采用返回的钱包标识
const featureInfo = await ukeySdk.getFeatures(connectId);
if (!featureInfo.success) throw new Error(featureInfo.payload.error);
const resolvedDeviceId = featureInfo.payload.device_id ?? deviceId;

// 3) 参考写法:读取 BTC 地址
const addressResult = await ukeySdk.btcGetAddress(connectId, resolvedDeviceId, {
path: "m/84'/0'/2'/0/0",
coin: "btc",
showOnUKey: false,
});

if (addressResult.success) {
console.log("解析出的 BTC 地址:", addressResult.payload.address);
} else {
console.error("调用失败:", addressResult.payload.error, addressResult.payload.code);
}

收尾清单

  • 把旧版 @ukeyfe/hardware-web-sdk 换成 @ukeyfe/hardware-common-connect-sdk,不要再保留 Bridge 入口。
  • 初始化时直接走 env: 'webusb',原来的 connectSrc 相关配置可以一并删掉。
  • 诸如 checkBridgeStatus()、Bridge 安装页、重启提醒这类逻辑,都可以按旧通道清理掉。
  • 事件层面要补齐 UI_EVENT / DEVICE,PIN、Passphrase 以及设备插拔都要有对应处理。
  • 设备授权前先别做自动枚举,requestDevice() 应该由按钮点击等用户动作触发。
  • 如果浏览器没有 navigator.usb,就引导用户切到支持 WebUSB 的桌面环境。

问答

  • HTTP 页面没有权限提示?请改为 HTTPS 或本地安全上下文。
  • UI 请求卡住的时候,先确认是否提前订阅了 UI_EVENT,并在收到事件后调用 uiResponse
  • 仍然配置 connectSrc?说明代码还停留在 iframe 方案,需要切换到 hardware-common-connect-sdk 的 WebUSB 初始化。
  • requestDevice 没有响应?先确认是否由按钮点击等用户手势触发。

延读