快速开始
交易优化
优化计算单元、优先费用和交易发送
数据检索
高效获取账户和程序数据的模式
实时监控
WebSocket 订阅和流数据优化
最佳实践
性能指南和资源管理
交易优化
计算单元管理
1. 模拟以确定实际使用情况:const testTransaction = new VersionedTransaction(/* your transaction */);
const simulation = await connection.simulateTransaction(testTransaction, {
replaceRecentBlockhash: true,
sigVerify: false
});
const unitsConsumed = simulation.value.unitsConsumed;
const computeUnitLimit = Math.ceil(unitsConsumed * 1.1);
const computeUnitIx = ComputeBudgetProgram.setComputeUnitLimit({
units: computeUnitLimit
});
instructions.unshift(computeUnitIx); // Add at beginning
优先费用优化
1. 获取动态费用估算:const response = await fetch(`https://mainnet.helius-rpc.com/?api-key=${API_KEY}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
method: 'getPriorityFeeEstimate',
params: [{
accountKeys: ['11111111111111111111111111111112'], // System Program
options: { recommended: true }
}]
})
});
const { priorityFeeEstimate } = await response.json().result;
const priorityFeeIx = ComputeBudgetProgram.setComputeUnitPrice({
microLamports: priorityFeeEstimate
});
instructions.unshift(priorityFeeIx);
交易发送最佳实践
- 标准方法
- 带确认
// Serialize and encode
const serializedTx = transaction.serialize();
const signature = await connection.sendRawTransaction(serializedTx, {
skipPreflight: true, // Saves ~100ms
maxRetries: 0 // Handle retries manually
});
// Send and confirm with custom logic
const signature = await connection.sendRawTransaction(serializedTx);
// Monitor confirmation
const confirmation = await connection.confirmTransaction({
signature,
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
});
数据检索优化
增强分页方法 (V2)
对于大规模数据查询,使用新的 V2 方法与基于游标的分页:⚡ 性能提升
getProgramAccountsV2 和 getTokenAccountsByOwnerV2 为处理大型数据集的应用程序提供了显著的性能提升:- 可配置限制:每个请求1-10,000个账户
- 基于游标的分页:防止大型查询超时
- 增量更新:使用
changedSinceSlot进行实时同步 - 更好的内存使用:流式传输数据而不是一次性加载所有内容
// ❌ Old approach - could timeout with large datasets
const allAccounts = await connection.getProgramAccounts(programId, {
encoding: 'base64',
filters: [{ dataSize: 165 }]
});
// ✅ New approach - paginated with better performance
let allAccounts = [];
let paginationKey = null;
do {
const response = await fetch(`https://mainnet.helius-rpc.com/?api-key=${API_KEY}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: '1',
method: 'getProgramAccountsV2',
params: [
programId,
{
encoding: 'base64',
filters: [{ dataSize: 165 }],
limit: 5000,
...(paginationKey && { paginationKey })
}
]
})
});
const data = await response.json();
allAccounts.push(...data.result.accounts);
paginationKey = data.result.paginationKey;
} while (paginationKey);
// Get only accounts modified since a specific slot
const incrementalUpdate = await fetch(`https://mainnet.helius-rpc.com/?api-key=${API_KEY}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: '1',
method: 'getProgramAccountsV2',
params: [
programId,
{
encoding: 'jsonParsed',
limit: 1000,
changedSinceSlot: lastProcessedSlot // Only get recent changes
}
]
})
});
数据检索优化
高效账户查询
- 单个账户
- 多个账户
- 程序账户
// Use dataSlice to reduce payload size
const accountInfo = await connection.getAccountInfo(pubkey, {
encoding: 'base64',
dataSlice: { offset: 0, length: 100 }, // Only get needed data
commitment: 'confirmed'
});
// Batch multiple account queries
const accounts = await connection.getMultipleAccountsInfo([
pubkey1, pubkey2, pubkey3
], {
encoding: 'base64',
commitment: 'confirmed'
});
// Use filters to reduce data transfer
const accounts = await connection.getProgramAccounts(programId, {
filters: [
{ dataSize: 165 }, // Token account size
{ memcmp: { offset: 0, bytes: mintAddress }}
],
encoding: 'jsonParsed'
});
代币余额查询
// Don't do this - requires N+1 RPC calls
const tokenAccounts = await connection.getTokenAccountsByOwner(owner, {
programId: TOKEN_PROGRAM_ID
});
const balances = await Promise.all(
tokenAccounts.value.map(acc =>
connection.getTokenAccountBalance(acc.pubkey)
)
);
// ~500ms + (100ms * N accounts)
// Single call with parsed data
const tokenAccounts = await connection.getTokenAccountsByOwner(owner, {
programId: TOKEN_PROGRAM_ID
}, { encoding: 'jsonParsed' });
const balances = tokenAccounts.value.map(acc => ({
mint: acc.account.data.parsed.info.mint,
amount: acc.account.data.parsed.info.tokenAmount.uiAmount
}));
// ~500ms total - 95% reduction for large wallets
交易历史
若要获取完整的地址历史记录,请使用getTransactionsForAddress ——这是 Helius 独有的方法,可以在单个调用中返回完整的交易数据,包括关联的代币账户活动:
// Avoid sequential transaction fetching
const signatures = await connection.getSignaturesForAddress(address, { limit: 100 });
const transactions = await Promise.all(
signatures.map(sig => connection.getTransaction(sig.signature))
);
// ~1s + (200ms * 100 txs) = ~21s
// Also note: getSignaturesForAddress doesn't include token account transactions
// Use getTransactionsForAddress for full history including token accounts
const response = await fetch(`https://mainnet.helius-rpc.com/?api-key=${API_KEY}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'getTransactionsForAddress',
params: [
address,
{
transactionDetails: 'full',
limit: 100,
filters: { tokenAccounts: 'balanceChanged' }
}
]
})
});
// ~100ms total - includes complete token history in one call
转账历史
当您只需要代币或SOL的移动—付款、投资组合活动、余额对账—请使用getTransfersByAddress (Helius 独有,需要开发者计划或更高级别)。它返回已解析的、可人类阅读的转账对象,其中所有者、铸币、金额和小数点均已解决,因此您可以完全跳过交易解析:
// Parsed USDC transfers received by a wallet - no manual parsing needed
const response = await fetch(`https://mainnet.helius-rpc.com/?api-key=${API_KEY}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'getTransfersByAddress',
params: [
address, // Wallet owner address, not a token account
{
mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
direction: 'in',
limit: 100
}
]
})
});
// Each transfer includes parsed sender, recipient, amount, decimals, and uiAmount
getTransactionsForAddress;当您需要清晰的转账记录用于分类账和付款跟踪时,请使用 getTransfersByAddress。
实时监控
账户订阅
// Avoid polling - wastes resources
setInterval(async () => {
const accountInfo = await connection.getAccountInfo(pubkey);
// Process updates...
}, 1000);
// Use WebSocket subscriptions for real-time updates
const subscriptionId = connection.onAccountChange(
pubkey,
(accountInfo, context) => {
// Handle real-time updates
console.log('Account updated:', accountInfo);
},
'confirmed',
{ encoding: 'base64', dataSlice: { offset: 0, length: 100 }}
);
程序账户监控
// Monitor specific program accounts with filters
connection.onProgramAccountChange(
programId,
(accountInfo, context) => {
// Handle program account changes
},
'confirmed',
{
filters: [
{ dataSize: 1024 },
{ memcmp: { offset: 0, bytes: ACCOUNT_DISCRIMINATOR }}
],
encoding: 'base64'
}
);
交易监控
// Subscribe to transaction logs for real-time monitoring
const ws = new WebSocket(`wss://mainnet.helius-rpc.com/?api-key=${API_KEY}`);
ws.on('open', () => {
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'logsSubscribe',
params: [
{ mentions: [programId] },
{ commitment: 'confirmed' }
]
}));
});
ws.on('message', (data) => {
const message = JSON.parse(data);
if (message.params) {
const signature = message.params.result.value.signature;
// Process transaction signature
}
});
高级模式
智能重试逻辑
class RetryManager {
private backoff = new ExponentialBackoff({
min: 100,
max: 5000,
factor: 2,
jitter: 0.2
});
async executeWithRetry<T>(operation: () => Promise<T>): Promise<T> {
while (true) {
try {
return await operation();
} catch (error) {
if (error.message.includes('429')) {
// Rate limit - wait and retry
await this.backoff.delay();
continue;
}
throw error;
}
}
}
}
内存高效处理
// Process large datasets in chunks
function chunk<T>(array: T[], size: number): T[][] {
return Array.from({ length: Math.ceil(array.length / size) }, (_, i) =>
array.slice(i * size, i * size + size)
);
}
// Process program accounts in batches
const allAccounts = await connection.getProgramAccounts(programId, {
dataSlice: { offset: 0, length: 32 }
});
const chunks = chunk(allAccounts, 100);
for (const batch of chunks) {
const detailedAccounts = await connection.getMultipleAccountsInfo(
batch.map(acc => acc.pubkey)
);
// Process batch...
}
连接池化
class ConnectionPool {
private connections: Connection[] = [];
private currentIndex = 0;
constructor(rpcUrls: string[]) {
this.connections = rpcUrls.map(url => new Connection(url));
}
getConnection(): Connection {
const connection = this.connections[this.currentIndex];
this.currentIndex = (this.currentIndex + 1) % this.connections.length;
return connection;
}
}
const pool = new ConnectionPool([
'https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY',
'https://mainnet-backup.helius-rpc.com/?api-key=YOUR_API_KEY'
]);
性能监控
跟踪RPC使用
class RPCMonitor {
private metrics = {
calls: 0,
errors: 0,
totalLatency: 0
};
async monitoredCall<T>(operation: () => Promise<T>): Promise<T> {
const start = Date.now();
this.metrics.calls++;
try {
const result = await operation();
this.metrics.totalLatency += Date.now() - start;
return result;
} catch (error) {
this.metrics.errors++;
throw error;
}
}
getStats() {
return {
...this.metrics,
averageLatency: this.metrics.totalLatency / this.metrics.calls,
errorRate: this.metrics.errors / this.metrics.calls
};
}
}
最佳实践
承诺级别
- processed
- confirmed
- finalized
- 使用场景: WebSocket订阅、实时更新
- 延迟: ~400毫秒
- 可靠性: 适用于大多数应用
- 使用场景: 常规查询,账户信息
- 延迟: ~1秒
- 可靠性: 推荐用于大多数情况
- 使用场景: 最终结算,不可逆操作
- 延迟: ~32秒
- 可靠性: 最大确定性
资源管理
错误处理
// Implement robust error handling
async function robustRPCCall<T>(operation: () => Promise<T>): Promise<T> {
try {
return await operation();
} catch (error) {
if (error.code === -32602) {
// Invalid params - fix request
throw new Error('Invalid RPC parameters');
} else if (error.code === -32005) {
// Node behind - retry with different node
throw new Error('Node synchronization issue');
} else if (error.message.includes('429')) {
// Rate limit - implement backoff
throw new Error('Rate limited');
}
throw error;
}
}
常见陷阱需避免
避免这些常见错误:
- 使用轮询而不是 WebSocket 订阅
- 在只需要部分数据时获取完整账户数据
- 未使用批处理操作进行多次查询
- 忽视速率限制,未实现适当的重试逻辑
- 在足够时使用
confirmed承诺,而不是finalized - 未关闭订阅,导致内存泄漏
相关方法
本指南中的优化技术参考了以下 WebSocket 和 RPC 方法:getTransactionsForAddress
带有过滤、排序和代币账户支持的完整交易历史(Helius 独有)
getTransfersByAddress
用于支付和对账的解析代币和 SOL 转账历史(Helius 独有)
getTransaction
通过签名检索完整交易详情
getProgramAccounts
获取由程序拥有的所有账户
getTokenAccountsByOwner
获取钱包的代币账户
getMultipleAccountsInfo
批量获取多个账户详情
getAccountInfo
获取单个账户的信息
accountSubscribe
通过 WebSocket 订阅账户变动
programSubscribe
通过 WebSocket 订阅程序账户变动
logsSubscribe
通过 WebSocket 订阅交易日志
总结
通过实施这些优化技术,您可以实现:- 60-90% 的 API 调用量减少
- 实时操作的显著降低的延迟
- 通过目标查询减少带宽使用
- 具有智能重试逻辑的更好的错误弹性
- 通过高效的资源利用降低运营成本
下一步
准备好实施这些优化了吗?查看我们的交易优化指南,了解交易特定的最佳实践。