关于 openfort-backend-wallets
通过 Node.js SDK 管理 Openfort 后端钱包的开发技能,涵盖 EVM 与 Solana 钱包操作、签名、转账和 Gas 赞助,面向服务端自动化。
主要功能
- 01创建、列出、查询和删除钱包
- 02签署数据并提交区块链交易
- 03转移 EVM 与 Solana 资产
- 04导入和导出加密私钥
- 05配置费用赞助与策略
适用场景
- 01自动处理金库或薪资交易
- 02执行批量铸造、空投或支付
- 03为自主 AI Agent 提供钱包
- 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.mdfee-sponsorship.mdpolicy-engine.mdsetup.mdsolana-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)都通过两层身份验证:
- API 密钥——
Authorization标头中的 Bearer 令牌(sk_test_...或sk_live_...) - 钱包身份验证(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 流程:
- 在某条链上的首次调用:在链上注册 EIP-7702 委托(将 EOA 升级为智能账户),然后发送交易
- 后续调用:跳过委托,直接发送交易
- 多次交互会在单笔交易中以原子方式批处理(由智能账户委托启用)
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 流程的底层机制:
- Kora 提供费用支付方地址和区块哈希
- 将 Kora 设为费用支付方来构建交易
- 通过
simulateTransaction自动估算计算预算(失败时回退到 200k CU) - 用户签名 → Kora 联合签名 → RPC 提交
- 通过 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 创建
- 前往 Openfort Dashboard → Policies
- 创建策略并设置所需的条件规则
- 前往 Fee Sponsorship → 创建费用赞助并关联策略
- 复制费用赞助 ID(
pol_...) - 在代码中使用:
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) |
evmAddress | in、not in | addresses: Address[] |
evmNetwork | in、not in | chainIds: number[] |
evmData | in、not in、<、<=、>、>=、==、match | abi: string(JSON ABI)、functionName: string、args?: Record<string, unknown> |
evmMessage | match | pattern: string(RE2 正则表达式) |
evmTypedDataVerifyingContract | in、not in | addresses: Address[] |
evmTypedDataField | in、<=、match | fieldPath: string、values?: string[](用于 in)、value?: string(用于 <= / match) |
Solana 操作与条件
操作: signSolTransaction、sendSolTransaction、signSolMessage、sponsorSolTransaction
| 条件类型 | 运算符 | 字段 |
|---|---|---|
solAddress | in、not in | addresses: string[](base58) |
solValue | <=、>= | value: string(lamports) |
splAddress | in、not in | addresses: string[](base58) |
splValue | <=、>= | value: string(代币单位) |
mintAddress | ==、in | addresses: string[](base58 铸币地址) |
programId | in、not in | programIds: string[](base58) |
solNetwork | in、not in | networks: ('mainnet-beta' | 'devnet' | 'testnet')[] |
solMessage | match | pattern: string(RE2 正则表达式) |
solData | in、not in、<=、>=、==、match | idl: 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() |
DelegationError | Chain ID 不在 viem/chains 中且未提供 rpcUrl;或无 gas 流程失败 |
EncryptionError | 导入/导出期间 RSA 加密/解密失败 |
MissingWalletSecretError | 未配置 walletSecret 时尝试执行签名操作 |
MissingPublishableKeyError | 未配置 publishableKey 时尝试执行 Solana 操作 |
MissingAPIKeyError | 初始化时未提供 API key |
InvalidAPIKeyFormatError | API key 与 sk_test_* 或 sk_live_* 格式不符 |
InvalidWalletSecretFormatError | 钱包密钥不是有效的 EC P-256 密钥 |
InvalidPublishableKeyFormatError | Publishable key 与 pk_test_* 或 pk_live_* 格式不符 |
UserInputValidationError | 参数无效(例如缺少 viem 对等依赖) |
TimeoutError | 操作超时(例如 Solana 确认超时 60 秒) |
API 错误类
import {
APIError,
NetworkError,
ValidationError,
UnknownError,
} from '@openfort/openfort-node'
| 错误 | 字段 | 发生时机 |
|---|---|---|
APIError | statusCode、errorType、errorMessage、correlationId、errorLink | 来自 Openfort API 的 HTTP 错误 |
NetworkError | networkDetails | DNS 故障、超时、IP 被阻止、网关错误 |
ValidationError | field、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 签名验证 |