概述
交易监控使您能够实时跟踪 Solana 上的交易执行、成功/失败状态、程序交互和代币余额变化。本指南涵盖了不同交易监控用例的过滤策略和实际实现。先决条件: 本指南假设您已完成 Yellowstone gRPC 快速入门 并已设置好工作流。
交易过滤选项
- 程序过滤
- 特定账户
- 高级过滤
监控涉及特定程序的交易跟踪所有与您的程序交互的交易:
Report incorrect code
Copy
Ask AI
const subscribeRequest: SubscribeRequest = {
transactions: {
client: {
accountInclude: [
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // Token Program
"11111111111111111111111111111111", // System Program
"675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" // Your program
],
accountExclude: [],
accountRequired: [],
vote: false,
failed: false
}
},
commitment: CommitmentLevel.CONFIRMED
};
最佳用途: 程序特定监控、DeFi 协议跟踪、智能合约交互
实用示例
示例 1:监控 DEX 交易
跟踪所有涉及流行 DEX 程序的交易:Report incorrect code
Copy
Ask AI
import { StreamManager } from './stream-manager'; // From quickstart guide
async function monitorDEXTransactions() {
const streamManager = new StreamManager(
"your-grpc-endpoint",
"your-api-key",
handleDEXTransaction
);
const subscribeRequest: SubscribeRequest = {
transactions: {
client: {
accountInclude: [
"9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM", // Raydium V4
"675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8", // Raydium V5
"CAMMCzo5YL8w4VFF8KVHrK22GGUQpMpTFb6xRmpLFGNnSm", // Raydium CLMM
"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4" // Jupiter
],
vote: false,
failed: false
}
},
commitment: CommitmentLevel.CONFIRMED
};
await streamManager.connect(subscribeRequest);
}
function handleDEXTransaction(data: any): void {
if (data.transaction?.transaction) {
const tx = data.transaction.transaction;
console.log(`\n🔄 DEX Transaction:`);
console.log(` Signature: ${tx.signature}`);
console.log(` Slot: ${data.transaction.slot}`);
console.log(` Status: ${tx.meta?.err ? 'Failed' : 'Success'}`);
console.log(` Fee: ${tx.meta?.fee || 0} lamports`);
console.log(` Compute Units: ${tx.meta?.computeUnitsConsumed || 0}`);
// Show token balance changes
if (tx.meta?.preTokenBalances?.length > 0) {
console.log(` Token Balance Changes:`);
tx.meta.preTokenBalances.forEach((preBalance: any, index: number) => {
const postBalance = tx.meta.postTokenBalances[index];
if (preBalance && postBalance) {
const change = postBalance.uiTokenAmount.uiAmount - preBalance.uiTokenAmount.uiAmount;
if (change !== 0) {
console.log(` ${preBalance.mint}: ${change > 0 ? '+' : ''}${change}`);
}
}
});
}
}
}
示例 2:监控失败的交易
跟踪失败的交易以识别问题:Report incorrect code
Copy
Ask AI
async function monitorFailedTransactions() {
const streamManager = new StreamManager(
"your-grpc-endpoint",
"your-api-key",
handleFailedTransaction
);
const subscribeRequest: SubscribeRequest = {
transactions: {
client: {
accountInclude: ["YourProgramId"], // Your program
vote: false,
failed: true // Only failed transactions
}
},
commitment: CommitmentLevel.CONFIRMED
};
await streamManager.connect(subscribeRequest);
}
function handleFailedTransaction(data: any): void {
if (data.transaction?.transaction?.meta?.err) {
const tx = data.transaction.transaction;
console.log(`\n❌ Failed Transaction:`);
console.log(` Signature: ${tx.signature}`);
console.log(` Slot: ${data.transaction.slot}`);
console.log(` Error: ${JSON.stringify(tx.meta.err)}`);
console.log(` Fee: ${tx.meta.fee} lamports`);
console.log(` Compute Units: ${tx.meta.computeUnitsConsumed || 0}`);
// Log instruction details for debugging
if (tx.transaction?.message?.instructions) {
console.log(` Instructions:`);
tx.transaction.message.instructions.forEach((inst: any, i: number) => {
console.log(` ${i}: Program ${inst.programIdIndex}, Data: ${inst.data}`);
});
}
}
}
示例 3:监控高价值交易
跟踪具有显著 SOL 转移的交易:Report incorrect code
Copy
Ask AI
async function monitorHighValueTransactions() {
const streamManager = new StreamManager(
"your-grpc-endpoint",
"your-api-key",
handleHighValueTransaction
);
const subscribeRequest: SubscribeRequest = {
transactions: {
client: {
accountInclude: ["11111111111111111111111111111111"], // System Program
vote: false,
failed: false
}
},
commitment: CommitmentLevel.CONFIRMED
};
await streamManager.connect(subscribeRequest);
}
function handleHighValueTransaction(data: any): void {
if (data.transaction?.transaction?.meta) {
const tx = data.transaction.transaction;
const preBalances = tx.meta.preBalances || [];
const postBalances = tx.meta.postBalances || [];
// Calculate largest balance change
let maxChange = 0;
preBalances.forEach((preBalance: number, index: number) => {
const postBalance = postBalances[index] || 0;
const change = Math.abs(postBalance - preBalance);
maxChange = Math.max(maxChange, change);
});
// Only log transactions with > 10 SOL moved
const changeInSOL = maxChange / 1e9;
if (changeInSOL > 10) {
console.log(`\n💰 High-Value Transaction:`);
console.log(` Signature: ${tx.signature}`);
console.log(` Slot: ${data.transaction.slot}`);
console.log(` Max SOL Transfer: ${changeInSOL.toFixed(2)} SOL`);
console.log(` Fee: ${tx.meta.fee / 1e9} SOL`);
console.log(` Accounts: ${tx.transaction?.message?.accountKeys?.length || 0}`);
}
}
}
交易数据结构
理解交易数据结构有助于提取相关信息:交易消息结构
交易消息结构
核心交易数据:
Report incorrect code
Copy
Ask AI
{
signature: string;
isVote: boolean;
transaction: {
message: {
accountKeys: string[]; // All accounts involved
instructions: Instruction[]; // Program instructions
recentBlockhash: string; // Recent blockhash used
};
signatures: string[]; // Transaction signatures
};
meta: {
err: any; // Error details if failed
fee: number; // Transaction fee in lamports
computeUnitsConsumed: number; // Compute units used
preBalances: number[]; // Account balances before
postBalances: number[]; // Account balances after
preTokenBalances: TokenBalance[];
postTokenBalances: TokenBalance[];
logMessages: string[]; // Program log messages
};
}
代币余额变化
代币余额变化
代币余额结构:
Report incorrect code
Copy
Ask AI
{
accountIndex: number;
mint: string; // Token mint address
owner: string; // Account owner
uiTokenAmount: {
amount: string; // Raw token amount
decimals: number; // Token decimals
uiAmount: number; // Human-readable amount
uiAmountString: string; // String representation
};
}
指令详情
指令详情
程序指令结构:
Report incorrect code
Copy
Ask AI
{
programIdIndex: number; // Index in accountKeys array
accounts: number[]; // Account indices involved
data: string; // Instruction data (base58)
}
过滤逻辑参考
包含逻辑 (OR)
accountInclude: 交易必须涉及这些账户中的任意一个示例:
["A", "B"]
匹配涉及账户A或账户B的交易必需逻辑 (AND)
accountRequired: 交易必须涉及所有这些账户示例:
["A", "B"]
匹配涉及账户A和账户B的交易排除逻辑 (NOT)
accountExclude: 交易不得涉及任何这些账户示例:
["A", "B"]
排除涉及账户A或账户B的交易组合逻辑
最终过滤器:
(accountInclude OR empty) AND (accountRequired AND all) AND NOT (accountExclude OR any)
性能考虑
- 流量管理
- 数据处理
交易流可能是高流量的
- 从特定程序过滤器开始
- 适当地使用承诺级别
- 监控您的处理能力
- 实施背压处理
Report incorrect code
Copy
Ask AI
// Rate limiting example
let transactionCount = 0;
const startTime = Date.now();
function handleTransaction(data: any): void {
transactionCount++;
if (transactionCount % 100 === 0) {
const elapsed = (Date.now() - startTime) / 1000;
const rate = transactionCount / elapsed;
console.log(`Processing ${rate.toFixed(1)} tx/sec`);
}
// Your transaction processing logic
}
错误处理
常见的交易监控错误及解决方案:交易过多
交易过多
错误: 交易量过大解决方案:
- 添加更具体的过滤器(accountRequired, accountExclude)
- 使用更高的承诺级别以减少流量
- 实施采样或速率限制
- 异步处理交易
交易缺失
交易缺失
错误: 预期的交易未出现解决方案:
- 验证程序地址是否正确
- 检查交易是否实际发生
- 尝试使用PROCESSED承诺以获得更快的更新
- 确保过滤器不过于严格
解析错误
解析错误
错误: 无法解析交易数据解决方案:
- 优雅地处理缺失字段
- 在处理之前验证数据结构
- 记录有问题的交易以便调试
- 在解析逻辑周围使用 try-catch 块