React Native BLE (hd-ble-sdk)

Demo: React Native / Expo example → react-native-demo

This guide shows how to use the pure React Native BLE stack with @onekeyfe/hd-ble-sdk and @onekeyfe/hd-transport-react-native. No WebView or low-level adapter is required. The chain API usage stays the same as in Quick Start.

Install

We recommend installing the RN-native dependencies at the app layer so that autolinking includes the native modules in your Dev Client build:

npm i @onekeyfe/hd-ble-sdk @onekeyfe/hd-transport-react-native \
      @onekeyfe/react-native-ble-utils react-native-ble-plx \
      buffer process react-native-get-random-values react-native-url-polyfill

In your app entry (e.g., index.js or App.tsx):

// Polyfills (adjust to your project needs)
import 'react-native-get-random-values';
import 'react-native-url-polyfill/auto';
// @ts-ignore
global.Buffer = global.Buffer || require('buffer').Buffer;
// @ts-ignore
global.process = global.process || require('process');

// Register RN transport side-effects before SDK init
import '@onekeyfe/hd-transport-react-native';

import HardwareSDK from '@onekeyfe/hd-ble-sdk';

Android setup

Add permissions in AndroidManifest.xml (Android 12+):

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>

At runtime, request BLUETOOTH_SCAN and BLUETOOTH_CONNECT (and location on Android 12+). Ensure the system Location toggle is ON.

iOS setup

Add to Info.plist:

  • NSBluetoothAlwaysUsageDescription (required)

  • Optionally NSBluetoothPeripheralUsageDescription for older iOS versions

  • If your app uses the camera (e.g. QR scanning), add NSCameraUsageDescription

If using Expo, you can declare these in app.json under expo.ios.infoPlist and expo.android.permissions.

Metro config (polyfills & exports)

Map Node core APIs and enable package exports for subpath imports like @noble/hashes/blake2b:

// metro.config.js
config.resolver.extraNodeModules = {
  buffer: require.resolve('buffer/'),
  crypto: require.resolve('crypto-browserify'),
  stream: require.resolve('stream-browserify'),
  process: require.resolve('process/browser'),
  events: require.resolve('events/'),
  http: require.resolve('http-browserify'),
  https: require.resolve('https-browserify'),
  zlib: require.resolve('browserify-zlib'),
  util: require.resolve('util/'),
  url: require.resolve('url/'),
  path: require.resolve('path-browserify'),
};
config.resolver.unstable_enablePackageExports = true;

Build Dev Client (real devices)

Expo Go does not include your native BLE modules. Build a Dev Client:

# iOS
expo run:ios --device

# Android
expo run:android --device

# Start bundler for Dev Client
expo start --dev-client -c

Initialize and subscribe to events

export async function setupBle() {
  await HardwareSDK.init({
    env: 'react-native',                 // React Native BLE transport
    debug: __DEV__,
    fetchConfig: true,
  });

  // Subscribe to UI events (PIN / Passphrase / confirmations)
  // import { UI_EVENT, UI_REQUEST, UI_RESPONSE } from '@onekeyfe/hd-core'
  // HardwareSDK.on(UI_EVENT, (msg) => { /* open dialogs and reply via HardwareSDK.uiResponse(...) */ });
}

Discover devices and identify device_id

const devices = await HardwareSDK.searchDevices();
if (!devices.success) throw new Error(devices.payload.error);

// BLE returns id + name; fetch features to obtain device_id
const candidate = devices.payload[0];
const connectId = candidate.connectId;

const features = await HardwareSDK.getFeatures(connectId);
if (!features.success) throw new Error(features.payload.error);
const deviceId = features.payload.device_id;

Persist connectId and deviceId (most chain APIs require both).

First call example (BTC address)

const res = await HardwareSDK.btcGetAddress(connectId, deviceId, {
  path: "m/44'/0'/0'/0/0",
  coin: 'btc',
  showOnOneKey: false,
});

if (res.success) {
  console.log('BTC address:', res.payload.address);
} else {
  console.error('Error:', res.payload.error, res.payload.code);
}

Tips

  • Always subscribe early to UI_EVENT so PIN/Passphrase/confirmations do not stall requests. See Config Event.

  • Keep BLE permissions in sync with the OS version. Test on physical devices.

  • For additional examples, check: react-native-demo

Continue

Last updated

Was this helpful?