Transport ガイド

Openloop SDK は複数の接続方式(Transport)をサポートしています。dApp の対象プラットフォームに応じて適切な Transport を選択してください。

プラットフォーム対応表

Transport Chrome/Edge Firefox Safari (Desktop) iOS Safari Android Chrome Node.js / Electron
WebHID (USB)
Web Bluetooth
LocalWS
Safari Extension
USB HID (native)
WalletConnect

WalletConnect はデバイスと直接通信するのではなく、Openloop Connect アプリ経由のリモート署名です。デバイス操作(アドレス取得等)は Connect アプリ側で行われます。

選択フローチャート

Diagram 0

各 Transport 詳細


WebHID (USB)

パッケージ: @openloop/transport-webhid 対応環境: Chrome 89+ / Edge 89+(デスクトップのみ)

USB ケーブルでデバイスを直接接続します。最も高速で安定した接続方式です。

Static メソッド

メソッド 説明
isSupported(): boolean WebHID API が利用可能か
connect(): Promise<WebHidTransport> デバイスピッカーを表示して接続(ユーザージェスチャー必要)
reconnect(): Promise<WebHidTransport \| null> 以前許可されたデバイスに自動再接続

コード例

import { WebHidTransport } from '@openloop/transport-webhid'

// サポート確認
if (!WebHidTransport.isSupported()) {
  console.log('WebHID is not supported in this browser')
}

// 初回接続(ボタンクリック内で)
const transport = await WebHidTransport.connect()

// 自動再接続(ページ読み込み時)
const transport = await WebHidTransport.reconnect()

// 切断検知
transport.onDisconnect(() => {
  console.log('Device disconnected')
})

Web Bluetooth

パッケージ: @openloop/transport-webble 対応環境: Chrome 56+ / Edge 79+(デスクトップ)、Android Chrome

Bluetooth Low Energy (BLE) でワイヤレス接続します。

Static メソッド

メソッド 説明
isSupported(): boolean Web Bluetooth API が利用可能か
connect(): Promise<WebBleTransport> デバイスピッカーを表示して接続(ユーザージェスチャー必要)
reconnect(): Promise<WebBleTransport \| null> 以前ペアリングしたデバイスに再接続(Chrome 100+)

コード例

import { WebBleTransport } from '@openloop/transport-webble'

if (!WebBleTransport.isSupported()) {
  console.log('Web Bluetooth is not supported')
}

// 初回接続
const transport = await WebBleTransport.connect()

// 自動再接続
const transport = await WebBleTransport.reconnect()

注意事項


LocalWS(全ブラウザ対応)

パッケージ: @openloop/transport-local 対応環境: WebSocket をサポートする全ブラウザ 前提条件: Openloop Connect デスクトップアプリが起動していること

Openloop Connect デスクトップアプリが提供する WebSocket サーバー(ws://127.0.0.1:21320)経由で通信します。Firefox、Safari 等の WebHID/WebBLE 非対応ブラウザでも動作します。

Static メソッド

メソッド 説明
isAvailable(port?, host?): Promise<boolean> Connect サーバーが稼働しているか

コード例

import { LocalWsTransport } from '@openloop/transport-local'

// Connect アプリの起動確認
const available = await LocalWsTransport.isAvailable()

// 接続
const transport = new LocalWsTransport({
  port: 21320,    // デフォルト
  host: '127.0.0.1', // デフォルト
})
await transport.open()

// デバイス接続状態の変更通知
transport.onDeviceChange((connected: boolean) => {
  console.log('Device:', connected ? 'connected' : 'disconnected')
})

プロトコル

JSON-RPC 2.0 over WebSocket:

メソッド 説明
openloop_exchange APDU コマンド送受信
openloop_lock デバイスの排他ロック取得
openloop_unlock デバイスの排他ロック解放
openloop_status デバイス接続状態の取得

Safari Extension(iOS)

パッケージ: @openloop/transport-safari 対応環境: iOS Safari(Openloop Safari Extension インストール済み)

Safari Web Extension を経由して iOS の CoreBluetooth にアクセスし、BLE でデバイスと通信します。

Static メソッド

メソッド 説明
isAvailable(timeout?): Promise<boolean> Safari Extension がインストールされているか(デフォルト 3 秒タイムアウト)
scan(duration?): Promise<DeviceInfo[]> BLE デバイスをスキャン
connect(deviceId?): Promise<SafariTransport> デバイスに接続

コード例

import { SafariTransport } from '@openloop/transport-safari'

// Extension の確認
const available = await SafariTransport.isAvailable()

// デバイスのスキャン
const devices = await SafariTransport.scan(5000) // 5秒スキャン
console.log('Found devices:', devices)

// 接続
const transport = await SafariTransport.connect(devices[0]?.deviceId)

USB HID (Native)

パッケージ: @openloop/transport-usb 対応環境: Node.js / Electron 依存: node-hid

ブラウザを使わずに直接 USB デバイスと通信します。サーバーサイドやデスクトップアプリに適しています。

Static メソッド

メソッド 説明
discover(): UsbDeviceInfo[] 接続されている Openloop/Ledger デバイスを列挙

コード例

import { UsbHidTransport } from '@openloop/transport-usb'

// デバイス検出
const devices = UsbHidTransport.discover()
if (devices.length === 0) {
  console.log('No device found')
}

// 接続
const transport = new UsbHidTransport({ path: devices[0].path })
await transport.open()

// 自動リトライ(デフォルト最大3回)
const transport = new UsbHidTransport({
  path: devices[0].path,
  maxRetries: 3,
  exchangeTimeout: 120000, // 2分
})

WalletConnect

パッケージ: @openloop/sdk-core(WcTransport は sdk-core に含まれる) 対応環境: WebSocket をサポートする全ブラウザ

WalletConnect v2 リレー経由で、リモートの Openloop Connect アプリと通信します。カスタムメソッド openloop_exchange を使って APDU コマンドを中継します。

詳細は WalletConnect 連携 を参照してください。


OpenloopSDK クラスによる自動検出

OpenloopSDK クラスを使うと、利用可能な Transport を自動検出して接続できます。

import { OpenloopSDK, EthereumApp, DEFAULT_ETH_PATH } from '@openloop/sdk-core'
import { WebHidTransport } from '@openloop/transport-webhid'
import { WebBleTransport } from '@openloop/transport-webble'
import { LocalWsTransport } from '@openloop/transport-local'

// Transport を登録
OpenloopSDK.registerTransport('webhid', {
  factory: () => WebHidTransport.connect(),
  name: 'WebHID (USB)',
  isAvailable: () => WebHidTransport.isSupported(),
})

OpenloopSDK.registerTransport('webble', {
  factory: () => WebBleTransport.connect(),
  name: 'Web Bluetooth',
  isAvailable: () => WebBleTransport.isSupported(),
})

OpenloopSDK.registerTransport('local', {
  factory: async () => {
    const t = new LocalWsTransport()
    await t.open()
    return t
  },
  name: 'LocalWS (Connect)',
  isAvailable: () => LocalWsTransport.isAvailable(),
})

// 利用可能な Transport を確認
const transports = await OpenloopSDK.discover()
console.log(transports)
// [
//   { type: 'webhid', name: 'WebHID (USB)', available: true },
//   { type: 'webble', name: 'Web Bluetooth', available: true },
//   { type: 'local', name: 'LocalWS (Connect)', available: false },
// ]

// 指定した Transport で接続
const transport = await OpenloopSDK.connect({ transport: 'webhid' })

// または最初に利用可能な Transport で接続
const transport = await OpenloopSDK.connect()

再接続パターン

// ページ読み込み時に以前のデバイスへ自動再接続
async function autoReconnect(): Promise<ITransport | null> {
  // WebHID: 以前許可されたデバイスを検出
  if (WebHidTransport.isSupported()) {
    const transport = await WebHidTransport.reconnect()
    if (transport) return transport
  }

  // WebBLE: 以前ペアリングしたデバイスを検出(Chrome 100+)
  if (WebBleTransport.isSupported()) {
    const transport = await WebBleTransport.reconnect()
    if (transport) return transport
  }

  // LocalWS: Connect アプリが起動していれば接続
  if (await LocalWsTransport.isAvailable()) {
    const transport = new LocalWsTransport()
    await transport.open()
    return transport
  }

  return null
}

次のステップ