API リファレンス

全型定義・インターフェース・クラス・定数の一覧です。明記がなければ @openloop/sdk-core からエクスポートされています。

Swift Package (OpenloopShared) の API は本ドキュメントには未記載です。Swift API は openloop-connect/packages/mobile/ios/OpenloopShared/Sources/OpenloopShared/ のソースコードを直接参照してください。主要クラス: BleManager, BleTransport, Ctap2Builder, Ctap2Error, MakeCredentialParams, GetAssertionParams 等 (TypeScript 版 Ctap2App とほぼ同じ責務)。

目次


インターフェース

ITransport

デバイスとの通信を抽象化するインターフェース。全 Transport が実装します。

interface ITransport {
  open(): Promise<void>
  close(): Promise<void>
  isConnected(): boolean
  exchange(apdu: Uint8Array): Promise<Uint8Array>
  lock(): Promise<void>
  unlock(): Promise<void>
}
メソッド 説明
open() デバイスへの接続を開く
close() 接続を閉じる
isConnected() 接続中かどうか
exchange(apdu) APDU コマンドを送信してレスポンスを受信
lock() デバイスの排他アクセスを取得(マルチステップ操作用)
unlock() 排他アクセスを解放

TransportStatus

interface TransportStatus {
  connected: boolean
  deviceName?: string
  deviceId?: string
}

TransportEvent

type TransportEventType = 'connected' | 'disconnected' | 'error'

interface TransportEvent {
  type: TransportEventType
  error?: Error
}

type TransportEventHandler = (event: TransportEvent) => void

TransportInfo

OpenloopSDK.discover() が返す Transport 情報。

interface TransportInfo {
  type: string        // 登録名(例: 'webhid')
  name: string        // 表示名(例: 'WebHID (USB)')
  available: boolean  // 利用可能か
}

TransportFactory

type TransportFactory = () => Promise<ITransport>

SignatureResult

Ethereum / TRON の ECDSA 署名結果。

interface SignatureResult {
  v: number    // リカバリー ID
  r: string    // R 値 (32 bytes hex, 0x プレフィックスなし)
  s: string    // S 値 (32 bytes hex, 0x プレフィックスなし)
}

BtcMessageSignature

Bitcoin BIP-137 メッセージ署名結果。

interface BtcMessageSignature {
  v: number       // リカバリー ID (35-38: P2WPKH native SegWit)
  r: string       // R 値 (32 bytes hex)
  s: string       // S 値 (32 bytes hex)
  signature: string // 完全な署名 (V || R || S, 65 bytes) の Base64
}

InputSigningPath

Bitcoin PSBT の入力ごとの BIP32 パス指定。

interface InputSigningPath {
  index: number   // PSBT の入力インデックス
  path: string    // BIP32 パス(例: "84'/1'/0'/0/5")
}

DeviceInfo

interface DeviceInfo {
  connected: boolean
  path?: string
  vendorId?: number
  productId?: number
}

XrpSignatureResult

XRP 署名結果。

interface XrpSignatureResult {
  signature: string  // 署名 hex (Ed25519: 64B, secp256k1: DER 可変長)
}

XrpCurve

type XrpCurve = 'ed25519' | 'secp256k1'

WcSession

interface WcSession {
  topic: string
}

IWcSignClient

interface IWcSignClient {
  request<T>(params: {
    topic: string
    chainId: string
    request: { method: string; params: unknown }
  }): Promise<T>
}

WcTransportOptions

interface WcTransportOptions {
  client: IWcSignClient
  session: WcSession
  chainId?: string  // デフォルト: "eip155:1"
}

App クラス

EthereumApp

class EthereumApp {
  constructor(transport: ITransport)

  getAddress(path: string): Promise<{ publicKey: string; address: string }>

  signPersonalMessage(path: string, message: string, chainId?: number): Promise<SignatureResult>

  signTransaction(path: string, rawTx: string): Promise<SignatureResult>

  signTypedData(
    path: string, domainSeparatorHash: string, messageHash: string, chainId?: number
  ): Promise<SignatureResult>

  signAuthorization(path: string, authorizationRlp: string): Promise<SignatureResult>
}

BitcoinApp

class BitcoinApp {
  constructor(transport: ITransport)

  getAddress(testnet?: boolean): Promise<{ publicKey: string; address: string; chainCode: string }>

  getAddressWithPath(path: string): Promise<{ publicKey: string; address: string; chainCode: string }>

  getAccountXpub(coinType: number): Promise<{ publicKey: string; chainCode: string }>

  signMessage(message: string, path: string): Promise<BtcMessageSignature>

  signPsbt(psbt: Uint8Array | string): Promise<Uint8Array>

  signPsbtHex(psbt: string): Promise<string>

  signPsbtWithPaths(psbt: string, inputPaths: InputSigningPath[]): Promise<string>
}

SolanaApp

class SolanaApp {
  constructor(transport: ITransport)

  getAddress(path: string): Promise<{ publicKey: string; address: string }>

  signTransaction(path: string, txBytes: Uint8Array): Promise<string>

  signOffchainMessage(path: string, messageBytes: Uint8Array): Promise<string>
}

TronApp

class TronApp {
  constructor(transport: ITransport)

  getAddress(path: string): Promise<{ publicKey: string; address: string }>

  signTransaction(path: string, rawDataHex: string): Promise<SignatureResult>

  signMessage(path: string, message: string): Promise<SignatureResult>
}

XrpApp

class XrpApp {
  constructor(transport: ITransport)

  getAddress(path: string, curve?: XrpCurve): Promise<{ publicKey: string; address: string }>

  signTransaction(path: string, txBlob: string): Promise<XrpSignatureResult>
}

OpenloopApp

Openloop ファームウェア固有のユーティリティコマンドを扱うクラス。CLA=0xF0 (CLA_OPENLOOP) で公開されている独自コマンドを提供します。

class OpenloopApp {
  constructor(transport: ITransport)

  /**
   * GET_DEVICE_INFO (F0 A0) を送り、識別 + 状態 + フィーチャー情報を取得します。
   *
   * 戻り値:
   *   - 古い Openloop ファームウェア (v0.91.13 未満) や対応していない
   *     デバイスは null を返します
   *   - トランスポート層のエラーは throw します
   */
  getDeviceInfo(): Promise<OpenloopDeviceInfo | null>
}

OpenloopDeviceInfo

interface OpenloopDeviceInfo {
  modelId: number              // ハードウェア SKU ID(例: 0x0001 = Openloop V1)
  hwRevision: number           // PCB リビジョン
  mainFwVersion: { major: number; minor: number; patch: number }
  recoveryFwVersion: { major: number; minor: number; patch: number }
  state: number                // 16 bit 状態 bitmask(生値)
  stateBits: OpenloopDeviceState  // state を decode したビュー
  features: number             // 16 bit 機能 bitmask(実装詳細・将来変更あり)
}
フィールド 説明
modelId number ハードウェア SKU ID。新しい SKU が出るたびに増える
hwRevision number PCB リビジョン番号
mainFwVersion {major,minor,patch} 動作中のメインファームウェアバージョン
recoveryFwVersion {major,minor,patch} リカバリ(ファクトリー)パーティションのバージョン。取得不可なら全 0
state number 現在の状態を表す 16 bit bitmask(生値)
stateBits OpenloopDeviceState state を decode したオブジェクト
features number ハードウェア機能を表す 16 bit bitmask(生値)。bit 配置はファームウェア実装の詳細で、バージョンによって変わる可能性があります。 ホストアプリでは生値の保存・転送のみに使うことを推奨します

OpenloopDeviceState

state フィールドを decode した、人間に分かる形のオブジェクト。

interface OpenloopDeviceState {
  walletProvisioned: boolean
  language: number            // 0=英語, 1=日本語, 2-7=予約
  usbEnabled: boolean
  usbVidCompat: boolean       // false=Native (0x303A), true=Compatible (0x2C97)
  bleEnabled: boolean
  blePaired: boolean
  fidoEnabled: boolean
  pivEnabled: boolean
}

state bitmask レイアウト (FW v0.91.14+ で確定):

bit 名称 意味
0 WALLET_PROVISIONED ウォレット生成済み
1-3 LANG (3 bit) 言語インデックス(0=EN, 1=JA, …)
4 USB_ENABLED USB 通信 ON
5 USB_VID_COMPAT USB VID = Compatible mode (0x2C97)。0 のとき Native (0x303A)
6 BLE_ENABLED BLE 通信 ON
7 BLE_PAIRED BLE ペアリング済みデバイスあり
8 FIDO_ENABLED FIDO/Passkey 機能 ON
9 PIV_ENABLED PIV / PKCS#11 機能 ON
10-15 reserved 将来拡張用、現在は 0

将来 bit が追加される可能性があります。stateBits に存在しない bit を読みたい場合は生の state 値を直接マスクしてください。

使用例

import { OpenloopApp, formatOpenloopState } from '@openloop/sdk-core'

const app = new OpenloopApp(transport)
const info = await app.getDeviceInfo()

if (info === null) {
  console.log('GET_DEVICE_INFO not supported (old firmware)')
} else {
  console.log(`Model: 0x${info.modelId.toString(16).padStart(4, '0')}`)
  console.log(`FW: ${info.mainFwVersion.major}.${info.mainFwVersion.minor}.${info.mainFwVersion.patch}`)
  console.log(`State: ${formatOpenloopState(info.stateBits)}`)
  if (!info.stateBits.walletProvisioned) {
    // ウォレット未生成のときの分岐
  }
}

エラークラス

class OpenloopError extends Error {
  name: 'OpenloopError'
}

class ApduError extends OpenloopError {
  name: 'ApduError'
  readonly statusWord: number
  constructor(statusWord: number)
}

class TransportError extends OpenloopError {
  name: 'TransportError'
  constructor(message: string)
}

OpenloopSDK クラス

Transport の登録・検出・接続を管理するクラス。全メソッドは static です。

class OpenloopSDK {
  static registerTransport(type: string, config: {
    factory: TransportFactory
    name: string
    isAvailable: () => boolean | Promise<boolean>
  }): void

  static discover(): Promise<TransportInfo[]>

  static connect(opts?: { transport?: string }): Promise<ITransport>

  static getRegisteredTransports(): string[]

  static clearTransports(): void
}

WcTransport クラス

class WcTransport implements ITransport {
  constructor(options: WcTransportOptions)
  open(): Promise<void>
  close(): Promise<void>
  isConnected(): boolean
  lock(): Promise<void>
  unlock(): Promise<void>
  exchange(apdu: Uint8Array): Promise<Uint8Array>
}

定数

USB 識別子

const OPENLOOP_VENDOR_ID  = 0x303a   // Espressif VID
const OPENLOOP_PRODUCT_ID = 0x8341   // Openloop PID
const LEDGER_VENDOR_ID    = 0x2c97   // Ledger SAS VID
const LEDGER_PRODUCT_ID   = 0x1011   // Nano S 互換

BIP44 デフォルトパス

const DEFAULT_ETH_PATH  = "44'/60'/0'/0/0"
const BTC_MAINNET_PATH  = "84'/0'/0'/0/0"
const BTC_TESTNET_PATH  = "84'/1'/0'/0/0"
const DEFAULT_SOL_PATH  = "44'/501'/0'/0'"
const DEFAULT_TRON_PATH = "44'/195'/0'/0/0"
const DEFAULT_XRP_PATH  = "44'/144'/0'/0'/0'"

BLE 定数

const BLE_SERVICE_UUID      = '13d63400-2c97-0004-0000-4c6564676572'
const BLE_NOTIFY_UUID       = '13d63400-2c97-0004-0001-4c6564676572'
const BLE_WRITE_UUID        = '13d63400-2c97-0004-0002-4c6564676572'
const BLE_DEVICE_NAME_PREFIX = 'Openloop'
const BLE_DEFAULT_MTU       = 155

WalletConnect 定数

const WALLETCONNECT_PROJECT_ID = 'b3d610140c2d0d39f50150a030c7c985'

WalletConnect 対応チェーン (CAIP-2)

const SUPPORTED_EVM_CHAINS = [
  'eip155:1',         // Ethereum Mainnet
  'eip155:11155111',  // Sepolia Testnet
] as const

const SUPPORTED_BIP122_CHAINS = [
  'bip122:000000000019d6689c085ae165831e93', // Bitcoin Mainnet
  'bip122:000000000933ea01ad0ee984209779ba', // Bitcoin Testnet3
] as const

const SUPPORTED_SOLANA_CHAINS = [
  'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', // Mainnet Beta
  'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',  // Devnet
] as const

const SUPPORTED_TRON_CHAINS = [
  'tron:0x2b6653dc',  // TRON Mainnet
  'tron:0x94a9059e',  // TRON Shasta Testnet
] as const

WalletConnect 対応メソッド

const SUPPORTED_EVM_METHODS = [
  'eth_sendTransaction', 'eth_signTransaction', 'eth_sign',
  'personal_sign', 'eth_signTypedData', 'eth_signTypedData_v3',
  'eth_signTypedData_v4', 'wallet_getCapabilities',
] as const

const SUPPORTED_BIP122_METHODS = [
  'signPsbt', 'getAccountAddresses', 'signMessage', 'sendTransfer',
] as const

const SUPPORTED_SOLANA_METHODS = [
  'solana_signTransaction', 'solana_signAllTransactions',
  'solana_signAndSendTransaction', 'solana_signMessage',
] as const

const SUPPORTED_TRON_METHODS = [
  'tron_signTransaction', 'tron_signMessage',
] as const

const SUPPORTED_EVENTS = ['chainChanged', 'accountsChanged'] as const

APDU 命令セット

const APDU = {
  // クラスバイト
  CLA_ETHEREUM: 0xe0,         // Ledger 互換
  CLA_OPENLOOP: 0xf0,         // Openloop 独自

  // 共通 INS(coin_type で自動ルーティング)
  INS_GET_PUBLIC_KEY: 0x02,    // アドレス/公開鍵取得
  INS_SIGN_TX: 0x04,           // トランザクション署名
  INS_SIGN_MESSAGE: 0x08,     // メッセージ署名
  INS_SIGN_EIP712: 0x0c,      // EIP-712 Typed Data
  INS_SIGN_AUTHORIZATION: 0x34, // EIP-7702

  // Bitcoin PSBT(Openloop 独自)
  INS_BTC_SIGN_PSBT: 0x70,          // PSBT 送信
  INS_BTC_GET_SIGNED_PSBT: 0x71,    // 署名済み PSBT 取得
  INS_BTC_GET_WALLET_PUBLIC_KEY: 0x40, // BTC 公開鍵/アドレス取得
  INS_BTC_GET_ACCOUNT_XPUB: 0x72,   // アカウント xpub 取得
  INS_BTC_SIGN_MESSAGE: 0x73,       // BTC メッセージ署名

  // Solana(Ledger Solana 互換)
  INS_SOL_GET_PUBKEY: 0x05,         // Ed25519 公開鍵取得
  INS_SOL_SIGN_MESSAGE: 0x06,       // トランザクション/メッセージ署名
  INS_SOL_SIGN_OFFCHAIN_MSG: 0x07,  // オフチェーンメッセージ署名
} as const

ユーティリティ関数

// APDU コマンド構築
function buildApdu(cla: number, ins: number, p1: number, p2: number, data?: Uint8Array): Uint8Array

// BIP32 パスをバッファに変換
function pathToBuffer(path: string): Uint8Array

// BIP32 パスを要素配列に変換
function pathToElements(path: string): number[]

// Uint8Array の結合
function concat(...arrays: Uint8Array[]): Uint8Array

// hex 文字列を Uint8Array に変換(0x プレフィックスあり/なし対応)
function hexToBytes(hex: string): Uint8Array

// Uint8Array を hex 文字列に変換(0x プレフィックスなし)
function bytesToHex(bytes: Uint8Array): string

// Base58 エンコード/デコード
function base58Encode(bytes: Uint8Array): string
function base58Decode(str: string): Uint8Array

// OpenloopDeviceState を 1 行のログ用文字列に整形
// 例: "wallet=N lang=0 USB(native) ble=off FIDO PIV"
function formatOpenloopState(s: OpenloopDeviceState): string