On this page
Hardware SDK Core API Guide
Lifecycle how-to: init → search → events → first protected call → cleanup.
Parameter tables live in Common Params. Device and protocol differences live in Devices and Protocol V1 and V2.
Quick flow
- Call shape:
HardwareSDK.method(connectId, deviceId?, params)→Promise<{ success, payload }>; always guard onsuccessbefore touchingpayload. - Identifiers:
connectIdfromsearchDevices;deviceIdfromgetDeviceState(required for BLE, recommended for WebUSB). RefreshdeviceIdafter reset/recovery. Full table: Identifiers. - UI contract: subscribe
UI_EVENTonce; only calluiResponseon input-typeUI_REQUEST(PIN / Passphrase / Bootloader select). Route per device when several devices are connected. - Serialize calls per device. Reuse a hidden wallet by passing
passphraseStateon later methods (compatibility path:initSession + passphraseState). Do not callopenWalletSessionagain for that.
const res = await HardwareSDK.evmGetAddress(connectId, deviceId, {
path: "m/44'/60'/0'/0/0",
useEmptyPassphrase: true,
});
if (!res.success) throw new Error(res.payload.error);
console.log(res.payload.address);Interaction flow
Core identifiers & environments
| ID | Purpose | Obtain via | Changes when |
|---|---|---|---|
connectId | Which connection | searchDevices() | USB re-plug, BLE re-pair, transport switch |
deviceId | Which seed lifetime | getDeviceState (getFeatures is deprecated) | Wipe, recovery, seed switch |
USB and BLE connectId values for the same unit are different — cache them separately. See Identifiers and Disconnects and reconnection.
Runtime requirements
webusb— HTTPS + user gesture.react-native— BLE entitlement + (commonly) location permission.lowlevel— host BLE adapter forwarding raw notification chunks.- Firmware — some APIs fail in Bootloader.
Which identifiers are required?
| Requirement | Description | Example APIs |
|---|---|---|
| 🟢 No identifiers | SDK init, config, event management | init on/off searchDevices getLogs dispose uiResponse |
🟡 connectId only | Device management, status, firmware ops | getDeviceState openWalletSession cancel deviceSettings |
🔵 connectId + deviceId | Blockchain signing, address, encryption | evmSignTransaction btcSignTransaction solSignMessage allNetworkGetAddress |
Standard lifecycle (recommended)
init → search → getDeviceState → subscribe UI/DEVICE/FIRMWARE → call + uiResponse → cleanup
import HardwareSDK from '@onekeyfe/hd-common-connect-sdk';
import { UI_EVENT, UI_REQUEST, UI_RESPONSE } from '@onekeyfe/hd-core';
const initialized = await HardwareSDK.init({ env: 'webusb', fetchConfig: true, debug: false });
if (!initialized) throw new Error('SDK initialization failed');
const devices = await HardwareSDK.searchDevices();
if (!devices.success || !devices.payload.length) throw new Error('No device');
// Select explicitly in the application when more than one device is available.
if (devices.payload.length !== 1) throw new Error('Select exactly one device before continuing');
const { connectId } = devices.payload[0];
if (!connectId) throw new Error("Missing connectId");
const state = await HardwareSDK.getDeviceState(connectId);
if (!state.success) throw new Error(state.payload.error);
const deviceId = state.payload.identity.deviceId;
if (!deviceId) throw new Error("Device has no wallet identity");
// Register the UI_EVENT handler shown below before any protected call.
HardwareSDK.on(UI_EVENT, handleUiEvent);
const address = await HardwareSDK.evmGetAddress(connectId, deviceId, {
path: "m/44'/60'/0'/0/0",
useEmptyPassphrase: true,
});
if (!address.success) throw new Error(address.payload.error);Serialize per device. Refresh getDeviceState after a device switch. Remove listeners on unmount. Call HardwareSDK.dispose() only when tearing down the transport — see Disconnects and reconnection.
Common params
The full table, transport matrix, combos, and HD paths moved to Common Params.
HD path examples: Common Params → HD path.
For PIN and passphrase UX see PIN and Passphrase. New wallet-open code should use Wallet Sessions.
Events & UI wiring
Subscribe once near app start. Only call uiResponse for input requests. Copy payload.responseCorrelation onto each response when present; it identifies the pending interaction. Invalidate modal callbacks after cancellation or a UI-close event, and cancel the selected connection when the user dismisses input. Do not log UI event payloads or input values.
UI requests that require uiResponse
| UI_REQUEST | When it fires | Respond with |
|---|---|---|
REQUEST_PIN | Host PIN input request; device-only prompts need no reply | UI_RESPONSE.RECEIVE_PIN |
REQUEST_PASSPHRASE | Select host or device input (value: "", passphraseOnDevice: true for device input) | UI_RESPONSE.RECEIVE_PASSPHRASE |
REQUEST_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE | Web Bootloader chooser | UI_RESPONSE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE |
UI notifications (no uiResponse)
| UI_REQUEST | Purpose |
|---|---|
REQUEST_PASSPHRASE_ON_DEVICE | Enter the passphrase on the device; notification only |
REQUEST_BUTTON | Confirm on device. Firmware update uses reason='firmware-update' — still no uiResponse |
DEVICE_PROGRESS | Long-running task progress |
FIRMWARE_PROCESSING / FIRMWARE_PROGRESS / FIRMWARE_TIP | Firmware upgrade states |
BLUETOOTH_PERMISSION / LOCATION_PERMISSION | BLE permission prompts |
BOOTLOADER / REQUIRE_MODE / NOT_INITIALIZE / FIRMWARE_NOT_SUPPORTED | Mode or support hints |
Device / firmware events
| Channel | Event | Typical handling |
|---|---|---|
DEVICE.CONNECT | direct payload | Refresh device list |
DEVICE.DISCONNECT | direct payload | Invalidate the connection; do not replay side-effecting calls. Reconnect |
DEVICE.STATE / DEVICE.FEATURES / DEVICE.SUPPORT_FEATURES | direct payload | Update device state / features / supported features |
FIRMWARE_EVENT | RELEASE_INFO / BLE_RELEASE_INFO | Offer upgrade when safe. Firmware Update |
import HardwareSDK from '@onekeyfe/hd-common-connect-sdk';
import { UI_EVENT, UI_REQUEST, UI_RESPONSE } from '@onekeyfe/hd-core';
import type { UiEventMessage } from '@onekeyfe/hd-core';
// These modal functions are provided by your application's UI.
declare function openPinModal(submit: (input: { value: string }) => void): void;
declare function openPassphraseModal(submit: (input: { value: string; onDevice: boolean; save: boolean }) => void): void;
const handleUiEvent = (msg: UiEventMessage) => {
switch (msg.type) {
case UI_REQUEST.REQUEST_PIN:
if (msg.payload.deviceOnly || msg.payload.type === 'ButtonRequest_PinEntry' || msg.payload.type === 'ButtonRequest_AttachPin') {
// Display an on-device prompt; no uiResponse is needed.
return;
}
openPinModal(({ value }) =>
HardwareSDK.uiResponse({ ...msg.payload.responseCorrelation, type: UI_RESPONSE.RECEIVE_PIN, payload: value })
);
return;
case UI_REQUEST.REQUEST_PASSPHRASE:
if (msg.payload.deviceOnly) {
HardwareSDK.uiResponse({
...msg.payload.responseCorrelation,
type: UI_RESPONSE.RECEIVE_PASSPHRASE,
payload: { value: '', passphraseOnDevice: true, save: false },
});
return;
}
openPassphraseModal(({ value, onDevice, save }) =>
HardwareSDK.uiResponse({
...msg.payload.responseCorrelation,
type: UI_RESPONSE.RECEIVE_PASSPHRASE,
payload: { value: onDevice ? "" : value, passphraseOnDevice: onDevice, attachPinOnDevice: false, save },
})
);
return;
default:
break;
}
};
HardwareSDK.on(UI_EVENT, handleUiEvent);Errors
| Group | Common causes | Recommended actions |
|---|---|---|
| Device (101–118, 200) | Wrong mode, busy, deviceId mismatch, not initialized | Confirm mode, reconnect, re-run init + getDeviceState |
| IFrame (300–305) | Init missing, load/timeout/blocked | Ensure init succeeded; check CSP / iframe |
| Method/Firmware (400–418) | Bad params, firmware required, forbidden path | Validate HD path; Firmware Update |
| Transport (600–603) | Transport not configured, concurrent call | Check env, serialize calls |
| Bluetooth (700–722) | Scan/permission/connect/timeout | Permission, proximity; do not loop on a stale bond |
| Runtime/Bridge (800–822) | PIN cancelled, Bridge timeout | Respect cancellation; recover the connection without automatically replaying signing |
| Web device (901–902) | WebUSB not authorized | HTTPS + user gesture |
Map payload.code, not payload.error text. Definitions: HardwareError.ts.