Skip to main content

Move to Common

Use this migration path when a project is leaving the old Bridge channel and moving its SDK entry to @ukeyfe/hardware-common-connect-sdk. After the switch, the browser talks to UKey Wallet directly over WebUSB instead of going through the iframe Bridge.


Requirements

  • Use a desktop browser built on Chromium, such as Chrome or Edge.
  • Node.js 18 or later is recommended, with LTS preferred.

Key Changes

  • The SDK entry is switched from @ukeyfe/hardware-web-sdk to @ukeyfe/hardware-common-connect-sdk.
  • The initialization environment is changed to env: 'webusb', and connectSrc is no longer configured.
  • USB authorization must be triggered by a user gesture and opening the browser device selector via UKEY_WEBUSB_FILTER.
  • Interactions such as PIN, Passphrase, device plugging and unplugging are uniformly handled through the UI_EVENT / DEVICE event of @ukeyfe/hardware-core.
  • Removed Bridge-specific checks such as checkBridgeStatus(), Bridge installation prompt, and restart prompt.
  • Most of the business API names remain the same, such as searchDevices, getFeatures, btcGetAddress.

Setup

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

Init 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 uses WebUSB directly and does not rely on iframe, so connectSrc is not needed.
  • Keep fetchConfig: true and let the SDK pull the device capabilities and prompt configuration.

Bind Events

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: {
// For production, swap this out for your own PIN UI
await ukeySdk.uiResponse({
type: UI_RESPONSE.RECEIVE_PIN,
// Keep PIN entry on the hardware first (safer)
payload: "@@UKEY_INPUT_PIN_IN_DEVICE",
});
break;
}

case UI_REQUEST.REQUEST_PASSPHRASE: {
// For production, replace this with your Passphrase UI (device or software entry)
await ukeySdk.uiResponse({
type: UI_RESPONSE.RECEIVE_PASSPHRASE,
payload: { passphraseOnDevice: true, value: "" },
});
break;
}

default:
break;
}
});

ukeySdk.on(DEVICE.CONNECT, (payload: any) => {
console.log("Connected device event:", payload);
});
ukeySdk.on(DEVICE.DISCONNECT, (payload: any) => {
console.log("Disconnected device event:", payload);
});
}

bindDeviceEventHandlers();
  • Subscribe to UI_EVENT as early as possible, otherwise the request will be stuck waiting for no one to respond to the PIN, Passphrase or confirmation event.
  • For details, see: Configure events

Request USB Permission

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

// Call this from a click handler or another explicit user gesture; browsers block silent USB prompts.
await navigator.usb.requestDevice({ filters: UKEY_WEBUSB_FILTER });

Scan and Call

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

// 2) Optionally read featureInfo again to resolve the final device_id
const featureInfo = await ukeySdk.getFeatures(connectId);
if (!featureInfo.success) throw new Error(featureInfo.payload.error);
const resolvedDeviceId = featureInfo.payload.device_id ?? deviceId;

// 3) Sample: retrieve a BTC address
const addressResult = await ukeySdk.btcGetAddress(connectId, resolvedDeviceId, {
path: "m/84'/0'/2'/0/0",
coin: "btc",
showOnUKey: false,
});

if (addressResult.success) {
console.log("Resolved BTC address:", addressResult.payload.address);
} else {
console.error("Request failed:", addressResult.payload.error, addressResult.payload.code);
}

Wrap Up

  • Swap out @ukeyfe/hardware-web-sdk for @ukeyfe/hardware-common-connect-sdk, and drop the old Bridge entry path.
  • Move the browser init straight to env: 'webusb'; the old connectSrc wiring is no longer needed.
  • Anything Bridge-only, such as checkBridgeStatus(), install guidance, or restart reminders, can be removed with the migration.
  • Make sure UI_EVENT / DEVICE listeners are in place so PIN, Passphrase, and plug/unplug events are all covered.
  • Keep requestDevice() behind a user action instead of auto-enumerating before authorization.
  • If navigator.usb is missing, steer users to a desktop browser with WebUSB support.

Q&A

  • HTTP page has no permission prompt? Please change to HTTPS or local security context.
  • UI request stuck? First confirm whether UI_EVENT is subscribed in advance, and call uiResponse after receiving the event.
  • Still configure connectSrc? The description code is still stuck in the iframe scheme and needs to be switched to the WebUSB initialization of hardware-common-connect-sdk.
  • requestDevice not responding? Check whether the call is triggered by a user gesture such as a button click.

More Reading