最准确的方法:通过分析您的确切交易获取最高精度的优先费用估算。推荐用于对准确性要求最高的生产应用。
概述
序列化交易提供最准确的费用估算,因为 API 可以分析将在您的交易中执行的确切账户和操作。为什么使用序列化交易
- 最高准确性 - 分析确切操作
- 详细分析 - 指令特定模式
- 现实估算 - 反映实际交易
- 生产就绪 - 为关键应用构建
最佳适用场景
- 生产应用
- 复杂交易
- 关键操作
- 需要最大准确性
相较于账户密钥的优势
- 准确性优势
- 实际应用优势
指令特定分析
API 可以分析特定操作及其历史费用模式,而不仅仅是账户活动。
交易大小意识
考虑到交易的实际大小和复杂性,以提供更准确的估算。
只读账户处理
更好地分析交易上下文中的可写和只读账户。
实施指南
1
构建您的交易
创建包含所有指令的交易(优先费用除外)
2
序列化交易
将您的交易转换为序列化格式
3
获取费用估算
使用您的序列化交易调用优先费用 API
4
应用优先费用
添加优先费用指令并发送您的交易
快速入门示例
Report incorrect code
Copy
Ask AI
import {
Connection,
PublicKey,
Transaction,
SystemProgram,
ComputeBudgetProgram
} from "@solana/web3.js";
import bs58 from "bs58";
const connection = new Connection("https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY");
// 1. Build your transaction (without priority fee)
const transaction = new Transaction();
const transferIx = SystemProgram.transfer({
fromPubkey: senderKeypair.publicKey,
toPubkey: recipientPublicKey,
lamports: 1000000, // 0.001 SOL
});
transaction.add(transferIx);
// 2. Set required fields and serialize
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
transaction.feePayer = senderKeypair.publicKey;
const serializedTx = bs58.encode(transaction.serialize());
// 3. Get priority fee estimate
const priorityFee = await getPriorityFeeEstimate(connection, serializedTx, "Medium");
// 4. Add priority fee and send
transaction.instructions = []; // Reset
transaction.add(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }));
transaction.add(transferIx);
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
transaction.sign(senderKeypair);
核心实现功能
这是一个用于从序列化交易中获取优先费用估算的可重用函数:Report incorrect code
Copy
Ask AI
async function getPriorityFeeEstimate(connection, serializedTransaction, priorityLevel = "Medium") {
const response = await fetch(connection.rpcEndpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "getPriorityFeeEstimate",
params: [{
transaction: serializedTransaction,
options: {
priorityLevel: priorityLevel,
recommended: true
}
}]
})
});
const result = await response.json();
if (result.error) {
throw new Error(`Fee estimation failed: ${JSON.stringify(result.error)}`);
}
return result.result.priorityFeeEstimate;
}
完整实现示例
- 简单转账
- 代币转账
- 复杂多指令
展开查看完整示例
展开查看完整示例
Report incorrect code
Copy
Ask AI
const {
Connection,
PublicKey,
Transaction,
SystemProgram,
ComputeBudgetProgram,
sendAndConfirmTransaction,
Keypair
} = require("@solana/web3.js");
const bs58 = require("bs58");
// Initialize connection and accounts
const connection = new Connection("https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY");
const senderKeypair = Keypair.fromSecretKey(bs58.decode("YOUR_PRIVATE_KEY"));
const receiverPublicKey = new PublicKey("RECIPIENT_PUBLIC_KEY");
async function sendTransactionWithPriorityFee(amount, priorityLevel = "Medium") {
// 1. Create transaction with transfer instruction
const transaction = new Transaction();
const transferIx = SystemProgram.transfer({
fromPubkey: senderKeypair.publicKey,
toPubkey: receiverPublicKey,
lamports: amount,
});
transaction.add(transferIx);
// 2. Set required fields for serialization
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
transaction.feePayer = senderKeypair.publicKey;
// 3. Serialize the transaction
const serializedTransaction = bs58.encode(transaction.serialize());
// 4. Get priority fee estimate
const priorityFee = await getPriorityFeeEstimate(connection, serializedTransaction, priorityLevel);
console.log(`Estimated ${priorityLevel} priority fee: ${priorityFee} micro-lamports`);
// 5. Reset transaction and add priority fee instruction first
transaction.instructions = [];
// Add priority fee instruction
const priorityFeeIx = ComputeBudgetProgram.setComputeUnitPrice({
microLamports: priorityFee
});
transaction.add(priorityFeeIx);
// Re-add the original transfer instruction
transaction.add(transferIx);
// 6. Update blockhash and sign
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
transaction.sign(senderKeypair);
// 7. Send the transaction
try {
const signature = await sendAndConfirmTransaction(
connection,
transaction,
[senderKeypair],
{ maxRetries: 0 } // Set to 0 for staked connection usage
);
console.log(`Transaction successful with signature: ${signature}`);
return signature;
} catch (error) {
console.error("Error sending transaction:", error);
throw error;
}
}
// Usage
sendTransactionWithPriorityFee(1000000, "High"); // Send 0.001 SOL with high priority
高级配置选项
包含所有优先级别
包含所有优先级别
一次性获取所有优先级别的估算:
Report incorrect code
Copy
Ask AI
async function getAllPriorityLevels(connection, serializedTransaction) {
const response = await fetch(connection.rpcEndpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "getPriorityFeeEstimate",
params: [{
transaction: serializedTransaction,
options: {
includeAllPriorityFeeLevels: true
}
}]
})
});
const result = await response.json();
return result.result.priorityFeeLevels;
}
// Usage
const allLevels = await getAllPriorityLevels(connection, serializedTransaction);
console.log("All priority levels:", allLevels);
/*
Output:
{
"min": 0,
"low": 1000,
"medium": 5000,
"high": 15000,
"veryHigh": 50000,
"unsafeMax": 100000
}
*/
包含详细分析
包含详细分析
请求有关费用计算的详细信息:这提供了关于费用计算的见解,包括每个账户的分析。
Report incorrect code
Copy
Ask AI
async function getDetailedFeeAnalysis(connection, serializedTransaction) {
const response = await fetch(connection.rpcEndpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "getPriorityFeeEstimate",
params: [{
transaction: serializedTransaction,
options: {
includeDetails: true,
priorityLevel: "Medium"
}
}]
})
});
const result = await response.json();
console.log("Detailed analysis:", result.result);
return result.result;
}
自定义回溯期
自定义回溯期
调整分析的槽位数量:
Report incorrect code
Copy
Ask AI
async function getCustomLookbackEstimate(connection, serializedTransaction, lookbackSlots = 50) {
const response = await fetch(connection.rpcEndpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "getPriorityFeeEstimate",
params: [{
transaction: serializedTransaction,
options: {
priorityLevel: "Medium",
lookbackSlots: lookbackSlots // 1-150, default is 150
}
}]
})
});
const result = await response.json();
return result.result.priorityFeeEstimate;
}
// Compare different lookback periods
const recentEstimate = await getCustomLookbackEstimate(connection, serializedTx, 30);
const longerEstimate = await getCustomLookbackEstimate(connection, serializedTx, 100);
console.log(`Recent (30 slots): ${recentEstimate} micro-lamports`);
console.log(`Longer (100 slots): ${longerEstimate} micro-lamports`);
最佳实践
交易序列化
始终序列化实际交易,而不是简化版本
Report incorrect code
Copy
Ask AI
// ✅ Good - serialize actual transaction
const transaction = new Transaction();
transaction.add(actualInstruction1);
transaction.add(actualInstruction2);
const serialized = bs58.encode(transaction.serialize());
指令顺序
在估算交易中包含所有指令,除了优先费用
Report incorrect code
Copy
Ask AI
// ✅ Good - all business logic included
transaction.add(createAccountIx);
transaction.add(initializeIx);
transaction.add(transferIx);
// ❌ Don't include priority fee in estimation
错误处理策略
- 健壮的错误处理
- 简单的错误处理
Report incorrect code
Copy
Ask AI
class SerializedTransactionFeeEstimator {
constructor(connection) {
this.connection = connection;
this.fallbackFee = 10000; // 10k micro-lamports
}
async getEstimate(serializedTransaction, priorityLevel = "Medium") {
try {
// Primary attempt with serialized transaction
return await this.getPrimaryEstimate(serializedTransaction, priorityLevel);
} catch (error) {
console.warn("Serialized transaction estimate failed:", error.message);
// Fallback to account-based estimation
try {
return await this.getFallbackEstimate(serializedTransaction, priorityLevel);
} catch (fallbackError) {
console.warn("Fallback estimate failed:", fallbackError.message);
return this.getFallbackFee(priorityLevel);
}
}
}
async getPrimaryEstimate(serializedTransaction, priorityLevel) {
const response = await fetch(this.connection.rpcEndpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "getPriorityFeeEstimate",
params: [{
transaction: serializedTransaction,
options: {
priorityLevel: priorityLevel,
recommended: true
}
}]
})
});
const result = await response.json();
if (result.error) {
throw new Error(result.error.message);
}
return result.result.priorityFeeEstimate;
}
async getFallbackEstimate(serializedTransaction, priorityLevel) {
// Extract account keys from transaction and use account-based estimation
const transaction = Transaction.from(bs58.decode(serializedTransaction));
const accountKeys = transaction.instructions
.flatMap(ix => [ix.programId, ...ix.keys.map(k => k.pubkey)])
.map(key => key.toString());
const uniqueAccountKeys = [...new Set(accountKeys)];
// Use account-based estimation as fallback
const response = await fetch(this.connection.rpcEndpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: "1",
method: "getPriorityFeeEstimate",
params: [{
accountKeys: uniqueAccountKeys,
options: {
priorityLevel: priorityLevel,
recommended: true
}
}]
})
});
const result = await response.json();
if (result.error) {
throw new Error(result.error.message);
}
return result.result.priorityFeeEstimate;
}
getFallbackFee(priorityLevel) {
const fallbacks = {
"Low": 1000,
"Medium": 5000,
"High": 15000,
"VeryHigh": 50000
};
return fallbacks[priorityLevel] || 5000;
}
}
// Usage
const estimator = new SerializedTransactionFeeEstimator(connection);
const fee = await estimator.getEstimate(serializedTransaction, "High");
常见问题与解决方案
交易序列化错误
交易序列化错误
问题:序列化不完整交易时出错解决方案:在序列化之前始终设置所需字段:
Report incorrect code
Copy
Ask AI
// ✅ Always set these fields
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
transaction.feePayer = keypair.publicKey;
// Then serialize
const serialized = bs58.encode(transaction.serialize());
过期的Blockhash问题
过期的Blockhash问题
问题:使用过期的blockhash导致交易失败解决方案:在最终发送之前始终获取新的blockhash:
Report incorrect code
Copy
Ask AI
// Get estimate with temporary blockhash
const tempBlockhash = (await connection.getLatestBlockhash()).blockhash;
transaction.recentBlockhash = tempBlockhash;
const serialized = bs58.encode(transaction.serialize());
const priorityFee = await getPriorityFeeEstimate(connection, serialized, "Medium");
// Reset and rebuild with fresh blockhash
transaction.instructions = [];
transaction.add(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: priorityFee }));
transaction.add(originalInstruction);
// Get FRESH blockhash before sending
const freshBlockhash = (await connection.getLatestBlockhash()).blockhash;
transaction.recentBlockhash = freshBlockhash;
大型交易错误
大型交易错误
问题:交易过大无法序列化解决方案:使用版本化交易或分成多个交易:
Report incorrect code
Copy
Ask AI
import { VersionedTransaction, TransactionMessage } from "@solana/web3.js";
// For large transactions, use versioned transactions
const messageV0 = new TransactionMessage({
payerKey: keypair.publicKey,
recentBlockhash: (await connection.getLatestBlockhash()).blockhash,
instructions: [instruction1, instruction2, instruction3] // Many instructions
}).compileToV0Message();
const versionedTransaction = new VersionedTransaction(messageV0);
const serialized = bs58.encode(versionedTransaction.serialize());
何时使用 vs 账户密钥
使用序列化事务
生产应用
- 需要最大精度
- 复杂的多指令事务
- 关键操作
- 对性能敏感的应用
- 最终集成测试
- 性能优化
- 生产部署
使用账户密钥
开发与原型设计
- 开发期间的快速估算
- 简单事务
- 事务前规划
- 架构限制导致无法序列化
- 账户级费用模式分析
- 批量账户分析
- 快速市场研究