mcpField
O
openfort-backend-wallets

openfort-backend-wallets

github.com/openfort-xyz其他255 次安装5 周前更新
代码仓库

关于 openfort-backend-wallets

通过 Node.js SDK 管理 Openfort 后端钱包的开发技能,涵盖 EVM 与 Solana 钱包操作、签名、转账和 Gas 赞助,面向服务端自动化。

主要功能

  1. 01创建、列出、查询和删除钱包
  2. 02签署数据并提交区块链交易
  3. 03转移 EVM 与 Solana 资产
  4. 04导入和导出加密私钥
  5. 05配置费用赞助与策略

适用场景

  1. 01自动处理金库或薪资交易
  2. 02执行批量铸造、空投或支付
  3. 03为自主 AI Agent 提供钱包
  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 运行着两个完全隔离的环境:测试模式(sk_test_… / pk_test_…,仅限测试网)和正式模式(sk_live_… / pk_live_…,主网,真实资金)。在一个环境中创建的对象,无法在另一个环境中读取、用于签名或恢复。

  • 使用测试(开发)密钥创建的钱包仅存在于测试网。它不能用于生产环境,也绝不能用于托管或转移真实资金。
  • 要进入生产环境,请切换到正式密钥并创建全新钱包——绝不要在不同模式间迁移或重复使用测试钱包。
  • 密钥(sk_…)只能用于服务端。绝不要提交密钥或将其暴露给客户端。 参阅 https://openfort.io/docs/configuration/api-keys。

后端钱包是由服务端控制的 EOA,用于自动化区块链操作——无需用户交互。私钥存储在硬件支持的安全隔离区中,绝不会离开安全环境。

适用场景:后端钱包(相较于嵌入式钱包):

  • 服务端自动化:资金管理、批量铸造、薪资发放、空投
  • AI Agent 钱包:自主交易、支付处理
  • 程序化签名:无需浏览器或用户在场
  • 跨境支付:自动发放稳定币

更适合使用嵌入式钱包的场景:

  • 面向用户的钱包,密钥由用户控制
  • 需要用户批准的浏览器/移动端签名流程

设置

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)都通过两层身份验证:

  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 实现免 Gas)

sendTransaction 会自动处理完整的 EIP-7702 委托和免 Gas 流程:

  1. 在某条链上的首次调用:在链上注册 EIP-7702 委托(将 EOA 升级为智能账户),然后发送交易
  2. 后续调用:跳过委托,直接发送交易
  3. 多次交互会在单笔交易中以原子方式批处理(由智能账户委托启用)
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)

注意:如果在 viem/chains 中找不到 chainId,且未提供 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 会在内部处理端到端加密——只需提供原始私钥:

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 会在内部处理端到端解密——直接返回私钥:

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 交易默认均为免 Gas,通过 Kora 费用支付方协议实现。用户的钱包无需 SOL 支付 Gas 费。需要配置 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',
})
使用指令发送交易
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)

无 Gas 流程的底层机制:

  1. Kora 提供费用支付方地址和区块哈希
  2. 将 Kora 设为费用支付方来构建交易
  3. 通过 simulateTransaction 自动估算计算预算(失败时回退到 200k CU)
  4. 用户签名 → Kora 联合签名 → RPC 提交
  5. 通过 WebSocket 订阅确认(超时时间为 60s)
发送原始交易(预构建的 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 的十六进制或原始十六进制。会自动将 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)

Gas 赞助(费用赞助)

无 Gas 交易需要两步设置:先创建策略(规则),再创建与该策略关联的费用赞助(方案)。可通过 SDK 或 Openfort Dashboard 完成。

方案类型
方案说明
pay_for_user开发者全额赞助 Gas——用户无需支付
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,系统会自动发现项目范围内的费用赞助,并应用第一个匹配项。

费用赞助的增删改查
// 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'(单个账户)
  • 优先级:优先评估优先级较高的策略
  • 默认拒绝:没有匹配规则 = 拒绝操作
  • 规则:每个策略包含 1-10 条规则,包含 action('accept' | 'reject')、operation 和 criteria(AND 逻辑)
创建策略
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' },
      ],
    },
  ],
})
策略的增删改查
// 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 铸币地址)
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>
验证 Schema

SDK 导出用于 API 调用前进行客户端验证的 Zod Schema:

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()
DelegationErrorChain ID 不在 viem/chains 中且未提供 rpcUrl;或无 gas 流程失败
EncryptionError导入/导出期间 RSA 加密/解密失败
MissingWalletSecretError未配置 walletSecret 时尝试执行签名操作
MissingPublishableKeyError未配置 publishableKey 时尝试执行 Solana 操作
MissingAPIKeyError初始化时未提供 API key
InvalidAPIKeyFormatErrorAPI key 与 sk_test_* 或 sk_live_* 格式不符
InvalidWalletSecretFormatError钱包密钥不是有效的 EC P-256 密钥
InvalidPublishableKeyFormatErrorPublishable key 与 pk_test_* 或 pk_live_* 格式不符
UserInputValidationError参数无效(例如缺少 viem 对等依赖)
TimeoutError操作超时(例如 Solana 确认超时 60 秒)
API 错误类
import {
  APIError,
  NetworkError,
  ValidationError,
  UnknownError,
} from '@openfort/openfort-node'
错误字段发生时机
APIErrorstatusCode、errorType、errorMessage、correlationId、errorLink来自 Openfort 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 订阅处理超时

Account 对象速查

EVM Account
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 Account
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.*Gas 赞助的 CRUD 操作与启用/禁用
openfort.transactionIntents.*交易生命周期管理与 Gas 估算
openfort.iam.*用户管理与会话验证
openfort.paymasters.*ERC-4337 Paymaster 管理
openfort.contracts.*智能合约注册表
openfort.subscriptions.*事件订阅
openfort.triggers.*触发器管理
openfort.sessions.*会话密钥管理
openfort.players.*玩家管理(已弃用 → 请使用 iam.users)
openfort.auth.*第三方身份验证
openfort.constructWebhookEvent()Webhook 签名验证

评论

支持 Markdown