mcpField
O
openfort-backend-wallets

openfort-backend-wallets

github.com/openfort-xyzその他255 回インストール5 週間前に更新
リポジトリ

openfort-backend-wallets について

Node.js SDK で Openfort のバックエンドウォレットを管理する開発スキルです。EVM と Solana のウォレット操作、署名、送金、ガススポンサー設定を扱い、サーバー側の自動化に利用できます。

主な機能

  1. 01ウォレットの作成・一覧・取得・削除
  2. 02データ署名とブロックチェーン取引の送信
  3. 03EVM と Solana 資産の送金
  4. 04暗号化された秘密鍵のインポートとエクスポート
  5. 05手数料スポンサーとポリシーの設定

活用シーン

  1. 01トレジャリーや給与の取引を自動化
  2. 02一括ミント・エアドロップ・決済を実行
  3. 03自律型 AI エージェント用のウォレットを運用
  4. 04設定したポリシーで取引手数料を負担

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/openfort-xyz/agent-skills --skill openfort-backend-wallets

インストール後、Claude Code で/openfort-backend-walletsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
evm-wallets.md
fee-sponsorship.md
policy-engine.md
setup.md
solana-wallets.md

詳細

Openfort バックエンドウォレット(開発者カストディ)

⚠️ テストキーとライブキー — ウォレットを作成する前にお読みください。 Openfort は、完全に隔離された 2 つの環境で動作します。テストモード(sk_test_… / pk_test_…、テストネットのみ)とライブモード(sk_live_… / pk_live_…、メインネット、実際の資金)です。一方の環境で作成したオブジェクトを、もう一方の環境から読み取ったり、署名に使用したり、復元したりすることはできません。

  • テスト(開発)用シークレットキーで作成したウォレットは、テストネット上にのみ存在します。本番環境では使用できず、実際の資金を保管したり移動したりする用途には絶対に使用しないでください。
  • 本番環境へ移行するには、ライブシークレットキーに切り替え、新しいウォレットを作成してください。テストウォレットをモード間で移行したり、再利用したりしないでください。
  • シークレットキー(sk_…)はサーバー側でのみ使用してください。コミットしたり、クライアントに公開したりしないでください。 https://openfort.io/docs/configuration/api-keys を参照してください。

バックエンドウォレットは、ブロックチェーン操作を自動化するためのサーバー管理型 EOA で、ユーザーの操作は必要ありません。秘密鍵はハードウェアで保護されたセキュアエンクレーブに保存され、セキュア環境の外に出ることはありません。

バックエンドウォレットを使用する場面(埋め込みウォレットとの比較):

  • サーバー側の自動化:トレジャリー業務、一括ミント、給与支払い、エアドロップ
  • AI エージェント用ウォレット:自律取引、決済処理
  • プログラムによる署名:ブラウザーやユーザーが不要
  • 国際送金:ステーブルコインの自動送金

代わりに埋め込みウォレットを使用する場面:

  • ユーザーが鍵を管理する、ユーザー向けウォレット
  • ユーザーの承認を伴う、ブラウザー/モバイルでの署名フロー

セットアップ

npm install @openfort/openfort-node
# EVM peer dependency (required for sendTransaction):
npm install viem
# Solana peer dependencies (required for Solana operations):
npm install @solana/kit @solana-program/system @solana-program/compute-budget @solana-program/token @solana/kora @solana/transaction-confirmation
環境変数
OPENFORT_SECRET_KEY=sk_test_...            # Secret API key (required)
OPENFORT_WALLET_SECRET=...              # Base64-encoded EC P-256 private key (required for mutations)
OPENFORT_PUBLISHABLE_KEY=pk_test_...    # Required for Solana operations (Kora gasless)
OPENFORT_BASE_URL=https://api.openfort.io  # Optional, defaults to production
初期化
import Openfort from '@openfort/openfort-node'

const openfort = new Openfort(process.env.OPENFORT_SECRET_KEY!, {
  walletSecret: process.env.OPENFORT_WALLET_SECRET!,
  publishableKey: process.env.OPENFORT_PUBLISHABLE_KEY,
})

// Or use env vars directly (auto-detected):
// OPENFORT_SECRET_KEY, OPENFORT_WALLET_SECRET, OPENFORT_PUBLISHABLE_KEY
const openfort = new Openfort()
認証モデル

バックエンドウォレットへの変更リクエスト(/accounts/backend/* に対する POST、DELETE、PUT)は、次の2 層で認証されます。

  1. API キー — Authorization ヘッダー内の Bearer トークン(sk_test_... または sk_live_...)
  2. ウォレット認証(X-Wallet-Auth) — ウォレットシークレットで署名します。SDK がこれを自動的に生成します。

SDK が認証の生成を透過的に処理するため、初期化時に walletSecret を指定するだけです。

重要:ウォレット認証リクエストは、失敗しても再試行されません。それ以外のすべてのリクエストは、指数バックオフによる自動再試行が行われます。


EVM バックエンドウォレット

作成
const account = await openfort.accounts.evm.backend.create({
  wallet: 'pla_...', // Optional — associates the wallet with a player
})
// account.id       — 'acc_...'
// account.address  — '0x...' (viem Address type)
// account.walletId — 'wal_...'
// account.custody  — 'Developer'
一覧表示と取得
// List all EVM backend wallets (paginated)
const { accounts, total, nextPageToken } = await openfort.accounts.evm.backend.list({
  limit: 50,  // 1-100, default 10, optional
  skip: 0,    // optional
})

// Get by ID or address
const account = await openfort.accounts.evm.backend.get({ id: 'acc_...' })
// OR
const account = await openfort.accounts.evm.backend.get({ address: '0x...' })
// Throws AccountNotFoundError if not found
トランザクションの送信(EVM — EIP-7702 によるガス代無料)

sendTransaction は、EIP-7702 の委任とガス代無料のフロー全体を自動的に処理します。

  1. チェーン上での初回呼び出し:オンチェーンで EIP-7702 の委任を登録(EOA をスマートアカウントにアップグレード)し、その後トランザクションを送信します
  2. 2 回目以降の呼び出し:委任をスキップして、直接送信します
  3. 複数の操作は、1 つのトランザクションにまとめてアトミックに処理されます(スマートアカウントの委任によって有効になります)
const account = await openfort.accounts.evm.backend.create()

const result = await openfort.accounts.evm.backend.sendTransaction({
  account: account,           // Required — account object from create() or get()
  chainId: 84532,             // Required — target chain ID (resolved via viem/chains)
  interactions: [              // Required — array of contract calls (batched atomically)
    {
      to: '0xRecipientAddress',  // Required — destination address
      value: '0',                // Optional, default '0' — Wei amount as string
      data: '0x',                // Optional, default '0x' — calldata
    },
    // Add more interactions for atomic batching
  ],
  policy: 'pol_...',              // Optional — fee sponsorship ID for gasless tx
  rpcUrl: 'https://sepolia.base.org',  // Optional — custom RPC (required for chains not in viem/chains)
})

console.log('TX Hash:', result.response?.transactionHash)
console.log('Status:', result.response?.status)
console.log('Gas Used:', result.response?.gasUsed)

注:chainId が viem/chains に見つからず、rpcUrl も指定されていない場合は、DelegationError がスローされます。

データへの署名

アカウントオブジェクトは、複数の署名方式に対応しています。

const account = await openfort.accounts.evm.backend.get({ address: '0x...' })

// Sign a raw hash (32-byte hex)
const sig1 = await account.sign({ hash: '0xabcdef...' })

// Sign a human-readable message (EIP-191 personal_sign)
const sig2 = await account.signMessage({ message: 'Hello World' })

// Sign a serializable transaction
const sig3 = await account.signTransaction({
  to: '0x...',
  value: 100n,
  chainId: 84532,
})

// Sign EIP-712 typed data
const sig4 = await account.signTypedData({
  domain: { name: 'MyApp', version: '1', chainId: 84532 },
  types: { Transfer: [{ name: 'to', type: 'address' }, { name: 'amount', type: 'uint256' }] },
  primaryType: 'Transfer',
  message: { to: '0x...', amount: 100n },
})

または、より低レベルの API を直接使用します。

const signature = await openfort.accounts.evm.backend.sign({
  id: account.id,
  data: '0x...',  // hex-encoded data to sign
})
委任アカウントへの更新(EIP-7702)

トランザクションを送信せずに、EIP-7702 の委任を手動で登録します。

const delegatedAccount = await openfort.accounts.evm.backend.update({
  walletId: account.walletId,
  accountType: 'Delegated Account', // Required for EIP-7702 upgrade
  chainId: 84532,
  implementationType: 'Calibur',
  accountId: account.id,
})
秘密鍵のインポート

SDK が E2E 暗号化を内部的に処理するため、生の秘密鍵を指定するだけです。

const imported = await openfort.accounts.evm.backend.import({
  privateKey: '0xYourPrivateKeyHex', // hex string (with or without 0x prefix)
})
// imported.id, imported.address

内部の仕組み:SDK は転送前に、サーバーの公開鍵を使用して秘密鍵を RSA-OAEP(SHA-256)で暗号化します。サーバーは、対応する秘密鍵を KMS HSM(抽出不可)に保持しています。

低レベルの暗号化ヘルパー(上級者向け)

手動での暗号化ワークフロー(カスタムインポートパイプラインなど)向けに、SDK は次の機能もエクスポートしています。

import {
  generateRSAKeyPair,
  encryptForImport,
  decryptExportedPrivateKey,
  IMPORT_ENCRYPTION_PUBLIC_KEY,
} from '@openfort/openfort-node'

// These are synchronous functions:
const keyPair = generateRSAKeyPair()              // Returns { publicKey, privateKeyPem }
const encrypted = encryptForImport('0xKey', IMPORT_ENCRYPTION_PUBLIC_KEY) // Returns base64 string
const decrypted = decryptExportedPrivateKey(encryptedBase64, keyPair.privateKeyPem) // Returns hex string
秘密鍵のエクスポート

SDK が E2E 復号を内部的に処理し、秘密鍵を直接返します。

const privateKey = await openfort.accounts.evm.backend.export({
  id: account.id,
})
// privateKey is hex string (no 0x prefix)
削除
await openfort.accounts.evm.backend.delete(account.id)
// Permanently deletes wallet and private key — irreversible

Solana バックエンドウォレット

すべての Solana トランザクションは、Kora の手数料支払い者プロトコルにより、デフォルトでガス代無料です。 ユーザーのウォレットにガス代用の SOL は必要ありません。publishableKey の設定が必要です。

作成
const account = await openfort.accounts.solana.backend.create({
  wallet: 'pla_...', // Optional — associates the wallet with a player
})
// account.id      — 'acc_...'
// account.address — Base58 Solana address
// account.custody — 'Developer'
一覧表示と取得
const { accounts, total, nextPageToken } = await openfort.accounts.solana.backend.list({
  limit: 50,  // 1-100, default 10, optional
  skip: 0,    // optional
})

const account = await openfort.accounts.solana.backend.get({
  address: 'Base58Address...',
})
// Also: get({ id: 'acc_...' })
// Throws AccountNotFoundError if not found
SOL の送金
const result = await account.transfer({
  to: 'FDx9mfVqTvXUaSPQDELwDtGgMqxirmAFsEK2s4YsKfsc',
  amount: 1_000_000n,       // In lamports (1 SOL = 1_000_000_000 lamports)
  cluster: 'devnet',         // 'devnet' | 'mainnet-beta'
  // token defaults to 'sol'
  computeUnitLimit: 200_000,   // Optional — auto-estimated via simulation if omitted
  computeUnitPrice: 50_000n,   // Optional — micro-lamports priority fee
})
console.log('Signature:', result.signature)
SPL トークン(USDC など)の送金
// By token name
const usdcResult = await account.transfer({
  to: 'FDx9...',
  amount: 1_000_000n,  // In token base units (USDC: 6 decimals)
  token: 'usdc',
  cluster: 'devnet',
})

// By mint address
const splResult = await account.transfer({
  to: 'FDx9...',
  amount: 2_000_000n,
  token: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU', // Mint address
  cluster: 'devnet',
})
Instructions を使用してトランザクションを送信する
import { getTransferSolInstruction } from '@solana-program/system'
import { address, createNoopSigner } from '@solana/kit'

const account = await openfort.accounts.solana.backend.get({
  address: 'o24A5URLU3JNKg7AoeUrPsfsAo1NQeeAB4uQViAkpjq',
})

const ix = getTransferSolInstruction({
  source: createNoopSigner(address(account.address)),
  destination: address('FDx9mfVqTvXUaSPQDELwDtGgMqxirmAFsEK2s4YsKfsc'),
  amount: 10n,
})

const result = await openfort.accounts.solana.backend.sendTransaction({
  account,
  cluster: 'devnet',
  instructions: [ix],
  // computeUnitLimit — auto-estimated via simulation if omitted
  // computeUnitPrice — defaults to 50_000n micro-lamports
  // rpcUrl, wsUrl — custom endpoints (optional)
})
console.log('Signature:', result.signature)

内部でのガスレスフロー:

  1. Kora が手数料支払いアドレスとブロックハッシュを提供します
  2. Kora を手数料支払い者としてトランザクションを構築します
  3. simulateTransaction を使用して計算予算を自動推定します(失敗した場合は 200k CU にフォールバックします)
  4. ユーザーが署名し、Kora が共同署名して、RPC が送信します
  5. WebSocket サブスクリプションで確認します(タイムアウトは 60s)
Raw Transaction を送信する(Base64 形式で事前構築済み)
const result = await openfort.accounts.solana.backend.sendRawTransaction({
  account,
  cluster: 'devnet',
  transaction: base64EncodedTransaction,
})
// Internally decompiles, extracts instructions, re-wraps in gasless flow
データに署名する(Solana)
// Lower-level API
const signature = await openfort.accounts.solana.backend.sign(
  account.id,
  'hex_encoded_data',
)

// Account object methods
const sig1 = await account.signMessage({ message: 'Hello Solana' })
const sig2 = await account.signTransaction({ transaction: base64Tx })
インポート/エクスポート(Solana)

EVM と同じ簡略化されたフローです。暗号化は内部で処理されます。Solana のインポートでは、base58、0x 付きの hex、または raw hex を使用できます。32 バイトのシードは、64 バイトのキーペアに自動拡張されます。エクスポートでは base58(Solana の標準形式)が返されます。

// Import
const imported = await openfort.accounts.solana.backend.import({
  privateKey: '4YFq9y5f5hi77Bq8kDCE6VgqoAq...', // base58, hex with 0x, or raw hex
})

// Export
const privateKey = await openfort.accounts.solana.backend.export({
  id: account.id,
})
// privateKey is base58-encoded (standard Solana format)

ガススポンサーシップ(手数料スポンサーシップ)

ガスレス取引には、ポリシー(ルール)を作成し、そのポリシーに紐付けた手数料スポンサーシップ(戦略)を作成するという2 段階の設定が必要です。SDK または Openfort Dashboard から設定できます。

戦略の種類
戦略説明
pay_for_user開発者がガス代を全額負担します。ユーザーの支払いはありません
charge_custom_tokensユーザーは ERC-20 トークンで支払います(固定または動的な交換レート)
fixed_rateユーザーはトランザクションごとに固定額のトークンを支払います
SDK で作成する(プログラムによる作成)
// Step 1: Create a policy with criteria rules
const policy = await openfort.policies.create({
  scope: 'project',          // 'project' (all accounts) or 'account' (single account)
  description: 'Sponsor gas on Base for USDC contract',
  rules: [{
    action: 'accept',
    operation: 'sponsorEvmTransaction',
    criteria: [
      { type: 'evmNetwork', operator: 'in', chainIds: [8453] },
      { type: 'evmAddress', operator: 'in', addresses: ['0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'] },
    ],
  }],
})

// Step 2: Create a fee sponsorship linked to that policy
const sponsorship = await openfort.feeSponsorship.create({
  name: 'Base USDC Gas Sponsorship',
  strategy: { sponsorSchema: 'pay_for_user' },
  policyId: policy.id,
})

// Step 3: Use sponsorship ID in transactions
await openfort.accounts.evm.backend.sendTransaction({
  account,
  chainId: 8453,
  interactions: [{ to: '0x...', value: '0', data: '0x...' }],
  policy: sponsorship.id,  // pol_... from sponsorship
})
Dashboard で作成する
  1. Openfort Dashboard に移動し、Policies を選択します
  2. 希望する条件ルールを設定してポリシーを作成します
  3. Fee Sponsorship に移動し、ポリシーを作成して紐付けます
  4. 手数料スポンサーシップ ID(pol_...)をコピーします
  5. コードで使用します:
await openfort.accounts.evm.backend.sendTransaction({
  account,
  chainId: 84532,
  interactions: [{ to: '0x...', value: '0', data: '0x' }],
  policy: process.env.OPENFORT_FEE_SPONSORSHIP_ID!, // pol_... from dashboard
})

自動検出:sendTransaction に policy が明示的に渡されていない場合、プロジェクトに紐付いた手数料スポンサーシップが自動検出され、最初に一致したものが適用されます。

手数料スポンサーシップの CRUD
// List
const sponsorships = await openfort.feeSponsorship.list()

// Get
const sponsorship = await openfort.feeSponsorship.get('pol_...')

// Update
await openfort.feeSponsorship.update('pol_...', { name: 'New Name' })

// Enable / Disable
await openfort.feeSponsorship.disable('pol_...')
await openfort.feeSponsorship.enable('pol_...')

// Delete (soft delete)
await openfort.feeSponsorship.delete('pol_...')
カスタムトークン請求戦略
const sponsorship = await openfort.feeSponsorship.create({
  name: 'Pay gas with USDC',
  strategy: {
    sponsorSchema: 'charge_custom_tokens',
    tokenContract: 'con_...',        // Contract ID from dashboard
    tokenContractAmount: '1000000',  // Amount in token base units
  },
  policyId: policy.id,
})

ポリシーエンジン

ポリシーは、許可または拒否する操作を制御するルールを定義します。署名やトランザクションの実行前に、サーバー側で評価されます。

主な概念:

  • スコープ:'project'(すべてのアカウント)または 'account'(単一のアカウント)
  • 優先度:優先度の高いポリシーから評価されます
  • フェイルクローズ:一致するルールがない場合、操作は拒否されます
  • ルール:各ポリシーには、action('accept' | 'reject')、operation、criteria(AND 条件)を含む 1~10 個のルールがあります
ポリシーを作成する
const policy = await openfort.policies.create({
  scope: 'project',
  description: 'Allow USDC transfers under 10k on Base',
  enabled: true,
  priority: 10,
  rules: [
    {
      action: 'accept',
      operation: 'sendEvmTransaction',
      criteria: [
        { type: 'evmNetwork', operator: 'in', chainIds: [8453] },
        { type: 'evmAddress', operator: 'in', addresses: ['0xUSDC_CONTRACT'] },
        { type: 'ethValue', operator: '<=', ethValue: '10000000000' },
      ],
    },
  ],
})
ポリシーの CRUD
// List policies
const policies = await openfort.policies.list({ scope: 'project', enabled: true })

// Get by ID
const policy = await openfort.policies.get('ply_...')

// Update (replaces all rules)
await openfort.policies.update('ply_...', {
  enabled: false,
  rules: [/* new rules */],
})

// Delete (soft delete)
await openfort.policies.delete('ply_...')

// Dry-run evaluation — check if an operation would be allowed without executing
const decision = await openfort.policies.evaluate({ /* operation details */ })
EVM の操作と条件

操作: signEvmTransaction、sendEvmTransaction、signEvmTypedData、signEvmMessage、signEvmHash、sponsorEvmTransaction

条件の種類演算子フィールド
ethValue<=、>=、<、>ethValue: string(wei)
evmAddressin、not inaddresses: Address[]
evmNetworkin、not inchainIds: number[]
evmDatain、not in、<、<=、>、>=、==、matchabi: string(JSON ABI)、functionName: string、args?: Record<string, unknown>
evmMessagematchpattern: string(RE2 正規表現)
evmTypedDataVerifyingContractin、not inaddresses: Address[]
evmTypedDataFieldin、<=、matchfieldPath: string、values?: string[](in 用)、value?: string(<=/match 用)
Solana の操作と条件

操作: signSolTransaction、sendSolTransaction、signSolMessage、sponsorSolTransaction

条件の種類演算子フィールド
solAddressin、not inaddresses: string[](base58)
solValue<=、>=value: string(lamports)
splAddressin、not inaddresses: string[](base58)
splValue<=、>=value: string(トークン単位)
mintAddress==、inaddresses: string[](base58 の mint アドレス)
programIdin、not inprogramIds: string[](base58)
solNetworkin、not innetworks: ('mainnet-beta' | 'devnet' | 'testnet')[]
solMessagematchpattern: string(RE2 正規表現)
solDatain、not in、<=、>=、==、matchidl: string(Anchor IDL JSON)、instructionName: string、args?: Record<string, unknown>
バリデーションスキーマ

SDK は、API 呼び出しの前にクライアント側で検証するための Zod スキーマをエクスポートします。

import {
  CreatePolicyBodySchema,
  UpdatePolicyBodySchema,
  RuleSchema,
} from '@openfort/openfort-node'

// Validate before sending
const parsed = CreatePolicyBodySchema.parse(myPolicyInput)

Webhook

タイミングセーフな比較を使用して、Openfort からの Webhook 署名を検証します。

// In your webhook handler (e.g., Express route)
app.post('/webhook', async (req, res) => {
  const signature = req.headers['openfort-signature'] as string
  const body = req.body // raw string body

  try {
    const event = await openfort.constructWebhookEvent(body, signature)
    // event is the parsed webhook payload
    console.log('Webhook event:', event)
    res.status(200).send('OK')
  } catch (error) {
    console.error('Invalid webhook signature')
    res.status(400).send('Invalid signature')
  }
})

トランザクションインテントのフロー(レガシー/高度な使い方)

トランザクションのライフサイクルをより細かく制御するには、トランザクションインテントを直接使用します。

// 1. Create transaction intent
const txIntent = await openfort.transactionIntents.create({
  chainId: 84532,
  account: 'acc_...',
  policy: 'pol_...', // Optional — fee sponsorship ID (from SDK or dashboard)
  interactions: [
    { to: '0x...', value: '0', data: '0x...' },
  ],
})

// 2. If signature needed
if (txIntent.nextAction?.payload?.signableHash) {
  const signature = await account.sign({
    hash: txIntent.nextAction.payload.signableHash,
  })

  // 3. Submit signature
  const result = await openfort.transactionIntents.signature(txIntent.id, {
    signature,
  })
  console.log('TX Hash:', result.response?.transactionHash)
}

// Estimate gas before creating
const estimate = await openfort.transactionIntents.estimateCost({
  chainId: 84532,
  interactions: [{ to: '0x...', value: '0', data: '0x...' }],
})

ライフサイクル全体の例

import Openfort from '@openfort/openfort-node'

const openfort = new Openfort(process.env.OPENFORT_SECRET_KEY!, {
  walletSecret: process.env.OPENFORT_WALLET_SECRET!,
  publishableKey: process.env.OPENFORT_PUBLISHABLE_KEY,
})

// 1. Create wallet
const wallet = await openfort.accounts.evm.backend.create()
console.log('Created:', wallet.address)

// 2. Set up gas sponsorship (policy + fee sponsorship)
const policy = await openfort.policies.create({
  scope: 'account',
  accountId: wallet.id,
  description: 'Only allow USDC on Base',
  rules: [{
    action: 'accept',
    operation: 'sponsorEvmTransaction',
    criteria: [
      { type: 'evmNetwork', operator: 'in', chainIds: [8453] },
      { type: 'evmAddress', operator: 'in', addresses: ['0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'] },
    ],
  }],
})

const sponsorship = await openfort.feeSponsorship.create({
  name: 'USDC Escrow Sponsorship',
  strategy: { sponsorSchema: 'pay_for_user' },
  policyId: policy.id,
})

// 3. Send gasless transaction
const tx = await openfort.accounts.evm.backend.sendTransaction({
  account: wallet,
  chainId: 8453, // Base mainnet
  interactions: [{
    to: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
    value: '0',
    data: '0x...transfer_calldata',
  }],
  policy: sponsorship.id,
})
console.log('TX:', tx.response?.transactionHash)

// 4. Export key if needed
const pk = await openfort.accounts.evm.backend.export({ id: wallet.id })
// pk is hex string (no 0x prefix)

エラー処理

SDK のエラークラス
import {
  AccountNotFoundError,
  DelegationError,
  EncryptionError,
  MissingWalletSecretError,
  MissingPublishableKeyError,
  MissingAPIKeyError,
  InvalidAPIKeyFormatError,
  InvalidWalletSecretFormatError,
  InvalidPublishableKeyFormatError,
  UserInputValidationError,
  TimeoutError,
} from '@openfort/openfort-node'
エラー発生する状況
AccountNotFoundError存在しない ID/アドレスを指定して .get() を呼び出した場合
DelegationErrorチェーン ID が viem/chains に含まれておらず、rpcUrl も指定されていない場合、またはガスレスフローに失敗した場合
EncryptionErrorインポート/エクスポート時の RSA 暗号化/復号に失敗した場合
MissingWalletSecretErrorwalletSecret が設定されていない状態で署名操作を試みた場合
MissingPublishableKeyErrorpublishableKey が設定されていない状態で Solana 操作を試みた場合
MissingAPIKeyError初期化時に API キーが指定されていない場合
InvalidAPIKeyFormatErrorAPI キーが sk_test_* または sk_live_* の形式と一致しない場合
InvalidWalletSecretFormatErrorウォレットシークレットが有効な EC P-256 キーではない場合
InvalidPublishableKeyFormatErrorPublishable Key が pk_test_* または pk_live_* の形式と一致しない場合
UserInputValidationErrorパラメーターが無効な場合(例:viem の peer dependency が不足している場合)
TimeoutError操作がタイムアウトした場合(例:Solana の確認が 60 秒でタイムアウトした場合)
API のエラークラス
import {
  APIError,
  NetworkError,
  ValidationError,
  UnknownError,
} from '@openfort/openfort-node'
エラーフィールド発生する状況
APIErrorstatusCode、errorType、errorMessage、correlationId、errorLinkOpenfort API からの HTTP エラー
NetworkErrornetworkDetailsDNS 失敗、タイムアウト、IP ブロック、ゲートウェイエラー
ValidationErrorfield、valueサーバー側の入力検証に失敗した場合
UnknownError—分類できないエラー

APIError.errorType の値:'unauthorized'、'forbidden'、'not_found'、'bad_request'、'conflict'、'rate_limited'、'bad_gateway'、'service_unavailable'、'unexpected_error'

堅牢なエラー処理パターン
import {
  AccountNotFoundError,
  DelegationError,
  MissingWalletSecretError,
  APIError,
  NetworkError,
} from '@openfort/openfort-node'

try {
  const result = await openfort.accounts.evm.backend.sendTransaction({ ... })
} catch (error) {
  if (error instanceof AccountNotFoundError) {
    // Wallet doesn't exist — create it or check ID
  } else if (error instanceof DelegationError) {
    // Provide rpcUrl for unsupported chains
  } else if (error instanceof MissingWalletSecretError) {
    // Configure walletSecret in Openfort constructor
  } else if (error instanceof APIError) {
    console.error(`API ${error.errorType}: ${error.errorMessage} [${error.correlationId}]`)
    // correlationId is useful for Openfort support debugging
  } else if (error instanceof NetworkError) {
    console.error('Network issue:', error.networkDetails)
    // Retried automatically (3x exponential backoff) unless wallet-auth request
  } else {
    throw error
  }
}

リトライと信頼性

SDK には、指数バックオフを使ったリトライ機能が組み込まれています。

  • リトライ対象:ネットワークエラー、5xx レスポンス、冪等なリクエスト(GET、HEAD、DELETE、PUT)
  • リトライ対象外:4xx エラー、ウォレット認証リクエスト
  • Solana の確認:WebSocket サブスクリプションを介したタイムアウト

アカウントオブジェクトのクイックリファレンス

EVM アカウント
const account = await openfort.accounts.evm.backend.get({ address: '0x...' })

account.id         // 'acc_...'
account.address    // '0x...' (viem Address)
account.walletId   // 'wal_...'
account.custody    // 'Developer'

account.sign({ hash })              // Sign raw 32-byte hash → Hex
account.signMessage({ message })    // EIP-191 personal_sign → Hex
account.signTransaction(tx)         // Sign serializable tx → Hex
account.signTypedData(params)       // EIP-712 typed data → Hex
Solana アカウント
const account = await openfort.accounts.solana.backend.get({ address: '...' })

account.id         // 'acc_...'
account.address    // Base58 string
account.custody    // 'Developer'

account.signMessage({ message })                      // Sign UTF-8 message → string
account.signTransaction({ transaction })              // Sign base64 tx → string
account.transfer({ to, amount, cluster, token? })     // SOL/SPL transfer → { signature }
account.sendRawTransaction({ cluster, transaction })  // Pre-built base64 tx → { signature }

SDK API の概要

バックエンドウォレットに加えて、@openfort/openfort-node SDK では以下を利用できます。

名前空間用途
openfort.accounts.evm.backend.*EVM バックエンドウォレットの操作
openfort.accounts.solana.backend.*Solana バックエンドウォレットの操作
openfort.accounts.evm.embedded.*埋め込み型 EVM ウォレットの事前生成
openfort.accounts.solana.embedded.*埋め込み型 Solana ウォレットの事前生成
openfort.policies.*ポリシーエンジンの CRUD と評価
openfort.feeSponsorship.*ガススポンサーシップの CRUD と有効化/無効化
openfort.transactionIntents.*トランザクションのライフサイクルとガス見積もり
openfort.iam.*ユーザー管理とセッション検証
openfort.paymasters.*ERC-4337 ペイマスターの管理
openfort.contracts.*スマートコントラクトレジストリ
openfort.subscriptions.*イベントサブスクリプション
openfort.triggers.*トリガー管理
openfort.sessions.*セッションキー管理
openfort.players.*プレイヤー管理(非推奨 → iam.users を使用)
openfort.auth.*サードパーティ認証の検証
openfort.constructWebhookEvent()Webhook 署名の検証

コメント