WebUSB Connection Guide

Demo: Playground (supports emulator) โ†’ hardware-example.onekey.so

Use this stepโ€‘byโ€‘step guide to wire WebUSB in the browser with @onekeyfe/hd-common-connect-sdk. Once connected, you can call any chain API (BTC/EVM/etc.) as in Quick Start.

Focus: WebUSB only.

Step 1. Requirements

  • Serve your app over HTTPS (WebUSB is blocked on insecure origins)

  • A browser that supports WebUSB (Chrome/Edge desktop)

  • A connected and unlocked OneKey device

Step 2. Install

npm i @onekeyfe/hd-common-connect-sdk @onekeyfe/hd-shared @onekeyfe/hd-core

Step 3. Initialize and bind events

Initialize the SDK during app startup and bind UI/device events so PIN/Passphrase and confirmations work end-to-end.

import HardwareSDK from '@onekeyfe/hd-common-connect-sdk';
import { UI_EVENT, UI_REQUEST, UI_RESPONSE, DEVICE } from '@onekeyfe/hd-core';

export async function setupWebUsb() {
  await HardwareSDK.init({
    env: 'webusb',
    debug: process.env.NODE_ENV !== 'production',
    fetchConfig: true,
  });

  bindHardwareEvents();
}

function bindHardwareEvents() {
  HardwareSDK.on(UI_EVENT, async (message: any) => {
    switch (message.type) {
      case UI_REQUEST.REQUEST_PIN: {
        // Show your PIN UI and respond via uiResponse
        const pinResult = await showPinDialog();
        if (pinResult.mode === 'device') {
          await HardwareSDK.uiResponse({
            type: UI_RESPONSE.RECEIVE_PIN,
            payload: '@@ONEKEY_INPUT_PIN_IN_DEVICE',
          });
        } else {
          await HardwareSDK.uiResponse({
            type: UI_RESPONSE.RECEIVE_PIN,
            payload: pinResult.value,
          });
        }
        break;
      }

      case UI_REQUEST.REQUEST_PASSPHRASE: {
        const passResult = await showPassphraseDialog();
        if (passResult.mode === 'device') {
          await HardwareSDK.uiResponse({
            type: UI_RESPONSE.RECEIVE_PASSPHRASE,
            payload: { passphraseOnDevice: true, value: '' },
          });
        } else {
          await HardwareSDK.uiResponse({
            type: UI_RESPONSE.RECEIVE_PASSPHRASE,
            payload: { value: passResult.value, passphraseOnDevice: false, save: passResult.save },
          });
        }
        break;
      }

      default:
        break;
    }
  });

  HardwareSDK.on(DEVICE.CONNECT, (payload: any) => {
    console.log('Device connected:', payload);
  });
  HardwareSDK.on(DEVICE.DISCONNECT, (payload: any) => {
    console.log('Device disconnected:', payload);
  });
}

Notes

  • Subscribe early to UI_EVENT so requests donโ€™t stall while waiting for PIN/Passphrase. See Config Event.

  • PIN: prefer on-device entry (@@ONEKEY_INPUT_PIN_IN_DEVICE). If you provide software input, use the blind keypad mapping (7,8,9,4,5,6,1,2,3).

  • Passphrase: support on-device input or software input, and optionally save for session caching.

  • Device events help you update UI if cables are unplugged.

Step 4. User authorization (chooser dialog with official filter)

Important: Must be triggered by a user gesture (e.g., clicking a button) due to Chrome security restrictions; automatic device discovery is not allowed before permission.

Use the ONEKEY_WEBUSB_FILTER filters so the chooser only shows supported devices.

Step 5. Enumerate and pick a device

  • USB results usually include deviceId in searchDevices().

  • Persist connectId/deviceId for subsequent calls.

Step 6. Get features (confirm device_id when needed)

Step 7. First call example (BTC address)

Appendix: Minimal UI helpers

Continue

Last updated

Was this helpful?