Shred Delivery and Sender are now live! Get earliest access to raw Solana data and optimized transaction sending. Learn about Shred Delivery | Learn about Sender
Shred Delivery and Sender are now live! Get earliest access to raw Solana data and optimized transaction sending. Learn about Shred Delivery | Learn about Sender
通过程序过滤、执行细节和代币余额变化跟踪,实时流式传输 Solana 交易。
const subscribeRequest: SubscribeRequest = {
transactions: {
client: {
accountInclude: [
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // Token Program
"11111111111111111111111111111111", // System Program
"675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8" // Your program
],
accountExclude: [],
accountRequired: [],
vote: false,
failed: false
}
},
commitment: CommitmentLevel.CONFIRMED
};
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}`);
}
}
});
}
}
}
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}`);
});
}
}
}
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}`);
}
}
}
交易消息结构
{
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
};
}
代币余额变化
{
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
};
}
指令详情
{
programIdIndex: number; // Index in accountKeys array
accounts: number[]; // Account indices involved
data: string; // Instruction data (base58)
}
["A", "B"]
匹配涉及账户A或账户B的交易["A", "B"]
匹配涉及账户A和账户B的交易["A", "B"]
排除涉及账户A或账户B的交易(accountInclude OR empty) AND (accountRequired AND all) AND NOT (accountExclude OR any)
// 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
}
交易过多
交易缺失
解析错误