Solana API

SolanaApp クラスは、Solana のアドレス取得、トランザクション署名、オフチェーンメッセージ署名を提供します。Ledger Solana アプリ互換の APDU プロトコルを使用します。

インポート

import {
  SolanaApp,
  DEFAULT_SOL_PATH,
} from '@openloop/sdk-core'

初期化

const sol = new SolanaApp(transport)

メソッド一覧

メソッド 説明
getAddress(path) Ed25519 公開鍵と Base58 アドレスを取得
signTransaction(path, txBytes) トランザクションに署名
signOffchainMessage(path, messageBytes) オフチェーンメッセージに署名

getAddress

デバイスから Solana アドレス(Ed25519 公開鍵の Base58 エンコード)を取得します。

async getAddress(path: string): Promise<{
  publicKey: string  // Ed25519 公開鍵 (hex, 32 bytes)
  address: string    // Base58 アドレス
}>

パラメータ

名前 説明
path string BIP44 パス(例: "44'/501'/0'/0'"

デフォルトパス

DEFAULT_SOL_PATH = "44'/501'/0'/0'"

注意: Solana は Ed25519 を使用するため、パスの全要素がハードニングされています。

使用例

const { address, publicKey } = await sol.getAddress(DEFAULT_SOL_PATH)
// address: "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"

signTransaction

Solana トランザクションのバイナリデータに Ed25519 署名を行います。

async signTransaction(
  path: string,
  txBytes: Uint8Array
): Promise<string>  // 64-byte Ed25519 署名 (hex)

パラメータ

名前 説明
path string BIP44 パス
txBytes Uint8Array シリアライズ済みトランザクション(raw binary)

返り値

64 バイトの Ed25519 署名(hex 文字列)

使用例

const signatureHex = await sol.signTransaction(
  DEFAULT_SOL_PATH,
  transactionBytes
)

注意: 大きなトランザクションは自動的に Ledger P2 チャンキングプロトコルで分割送信されます。


signOffchainMessage

オフチェーンメッセージ(Sign-In With Solana 等)に署名します。

async signOffchainMessage(
  path: string,
  messageBytes: Uint8Array
): Promise<string>  // 64-byte Ed25519 署名 (hex)

パラメータ

名前 説明
path string BIP44 パス
messageBytes Uint8Array メッセージの raw bytes

使用例

const message = new TextEncoder().encode('Hello, Solana!')
const signatureHex = await sol.signOffchainMessage(DEFAULT_SOL_PATH, message)

@solana/web3.js 連携

import {
  Connection,
  PublicKey,
  SystemProgram,
  Transaction,
} from '@solana/web3.js'
import { SolanaApp, DEFAULT_SOL_PATH } from '@openloop/sdk-core'
import { WebHidTransport } from '@openloop/transport-webhid'

const transport = await WebHidTransport.connect()
const sol = new SolanaApp(transport)

// アドレス取得
const { address } = await sol.getAddress(DEFAULT_SOL_PATH)
const publicKey = new PublicKey(address)

// トランザクション作成
const connection = new Connection('https://api.mainnet-beta.solana.com')
const recentBlockhash = (await connection.getLatestBlockhash()).blockhash

const tx = new Transaction()
tx.add(
  SystemProgram.transfer({
    fromPubkey: publicKey,
    toPubkey: new PublicKey('...'),
    lamports: 1000000, // 0.001 SOL
  })
)
tx.recentBlockhash = recentBlockhash
tx.feePayer = publicKey

// デバイスで署名
const txBytes = tx.serializeMessage()
const signatureHex = await sol.signTransaction(DEFAULT_SOL_PATH, txBytes)

// 署名をトランザクションに追加
const signatureBytes = Uint8Array.from(
  signatureHex.match(/.{2}/g)!.map(b => parseInt(b, 16))
)
tx.addSignature(publicKey, Buffer.from(signatureBytes))

// ブロードキャスト
const txId = await connection.sendRawTransaction(tx.serialize())
console.log('TX:', txId)

次のステップ