如何过滤getSignaturesForAddress结果中的SPL Token转账记录
过滤Solana SPL Token转账记录并获取金额
无需依赖LogMessage,解析交易指令更可靠
SPL Token转账本质是调用Token程序的transfer或transferChecked指令,直接从parsedTransaction的指令列表里筛选是最准确的方式,不用依赖LogMessage(部分转账可能没有输出日志):
- 先遍历交易的所有指令,筛选出程序ID匹配Token主网地址(
TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA)的指令 - 判断指令类型是否为
transfer或transferChecked - 检查指令中的
destination字段是否等于你的钱包地址,确保是转入而非转出记录
获取SPL Token转账数量的方法
- 对于
transfer指令:直接取amount字段,注意这个值是Token的最小单位(比如USDC的最小单位是1e-6),需要除以对应Token的decimals转换为可读金额 - 对于
transferChecked指令:除了amount,还能直接拿到decimals字段,省去单独查询Mint信息的步骤 - 如果需要decimals,可通过
getParsedAccountInfo查询对应Token Mint账户的信息
修改后的示例代码
import * as web3 from '@solana/web3.js'; // Solana主网Token程序地址 const TOKEN_PROGRAM_ID = new web3.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); const solanaConnection = new web3.Connection(web3.clusterApiUrl("mainnet-beta")); // 获取Token Mint的decimals const getTokenDecimals = async (mintAddress) => { const mintPubkey = new web3.PublicKey(mintAddress); const mintInfo = await solanaConnection.getParsedAccountInfo(mintPubkey); return mintInfo.value?.data.parsed.info.decimals || 0; }; const getTransactions = async(address, lastTransaction) => { const pubKey = new web3.PublicKey(address); const transactionList = await solanaConnection.getSignaturesForAddress(pubKey, {until: lastTransaction}); const signatureList = transactionList.map(tx => tx.signature); for await (const sig of signatureList) { // 加上交易版本参数,兼容版本化交易 const parsedTx = await solanaConnection.getParsedTransaction(sig, {maxSupportedTransactionVersion: 0}); if (!parsedTx) continue; // 遍历所有指令筛选SPL转入记录 for (const instr of parsedTx.transaction.message.instructions) { if (!instr.programId.equals(TOKEN_PROGRAM_ID)) continue; const parsedInstr = instr.parsed; if (['transfer', 'transferChecked'].includes(parsedInstr.type) && parsedInstr.info.destination === address) { const mintAddress = parsedInstr.info.mint; const rawAmount = parsedInstr.info.amount; // 若为transferChecked可直接用parsedInstr.info.decimals,无需单独查询 const decimals = parsedInstr.type === 'transferChecked' ? parsedInstr.info.decimals : await getTokenDecimals(mintAddress); const displayAmount = rawAmount / (10 ** decimals); console.log(`收到Token: ${displayAmount} (Mint地址: ${mintAddress})`); // 此处执行数据库更新逻辑 } } } } // 替换为你的钱包地址和上次处理的交易签名 getTransactions("你的钱包地址", lastTransaction);
注意事项
- 加上
maxSupportedTransactionVersion: 0参数,避免解析版本化交易时失败 - 务必校验
destination字段,防止把你主动转出的交易误判为转入 - 若处理大量交易,建议批量获取解析,减少
getParsedTransaction的调用次数,提升效率
内容的提问来源于stack exchange,提问作者oijafoijf asnjksdjn
相关产品推荐
相关产品推荐

