如何用JavaScript获取Solana区块链含购买代币量的交易历史?
如何用JavaScript获取Solana链上DEX代币购买交易记录
核心思路
Solana上的DEX交易(如Raydium、Serum)均通过调用对应DEX程序指令完成,要获取类似Dexscreener的实时购买记录,核心是:
- 连接Solana节点(主网/测试网)
- 订阅新区块或特定DEX程序的交易日志
- 解析交易指令,识别swap(代币购买)操作
- 提取交易中的代币数量、交易方等关键信息
实现步骤(以Raydium为例)
1. 安装依赖
先安装必要的JavaScript包:
npm install @solana/web3.js bs58
2. 连接节点并订阅交易
利用@solana/web3.js订阅Raydium AMM程序的交易,解析其中的swap指令。Raydium主网AMM程序地址为675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8。
示例代码:
const { Connection, PublicKey, clusterApiUrl } = require('@solana/web3.js'); const bs58 = require('bs58'); // 连接主网节点(建议用付费RPC如QuickNode避免限流,替换clusterApiUrl即可) const connection = new Connection(clusterApiUrl('mainnet-beta'), 'confirmed'); // Raydium AMM程序地址 const RAYDIUM_AMM_PROGRAM_ID = new PublicKey('675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8'); // 解析swap交易,提取关键信息 async function parseSwapTransaction(logEntry) { try { const transaction = await connection.getTransaction(logEntry.signature, { commitment: 'confirmed', maxSupportedTransactionVersion: 0 }); if (!transaction) return null; // 遍历交易指令,筛选AMM程序的swap指令 for (const instr of transaction.transaction.message.instructions) { if (instr.programId.equals(RAYDIUM_AMM_PROGRAM_ID)) { const data = bs58.decode(instr.data); // Raydium swap指令的前4字节标识符为0x03(需注意版本更新) const instructionId = data.slice(0, 4); if (instructionId.toString('hex') === '03000000') { // 解析交易数据:投入金额、最小产出金额、用户钱包、目标代币Mint地址 const amountIn = data.readBigUInt64LE(4); const amountOutMin = data.readBigUInt64LE(12); const userWallet = new PublicKey(instr.keys[0].pubkey); const tokenMint = new PublicKey(instr.keys[5].pubkey); return { signature: logEntry.signature, userAddress: userWallet.toString(), targetTokenMint: tokenMint.toString(), inputAmount: amountIn.toString(), minOutputAmount: amountOutMin.toString(), timestamp: transaction.blockTime }; } } } return null; } catch (err) { console.error('交易解析失败:', err); return null; } } // 订阅Raydium程序的交易日志,实时推送购买记录 async function subscribeToRaydiumSwaps() { const subscriptionId = connection.onLogs( `program ${RAYDIUM_AMM_PROGRAM_ID.toString()}`, async (logEntry, context) => { const swapRecord = await parseSwapTransaction(logEntry); if (swapRecord) { console.log('实时购买交易记录:', swapRecord); } }, 'confirmed' ); console.log('已启动Raydium交易订阅,订阅ID:', subscriptionId); } // 启动订阅 subscribeToRaydiumSwaps();
关键说明
- RPC节点选择:官方节点有请求限制,生产环境建议使用付费RPC保证稳定性和实时性。
- 指令ID适配:不同DEX的swap指令ID不同,比如Serum的swap指令ID为
0x0b,需查阅对应DEX的开源代码或文档确认。 - 多DEX覆盖:若要支持Orca、Phoenix等其他DEX,只需添加对应程序地址的订阅,并调整指令解析逻辑。
- 实时性优化:使用
onLogs订阅比轮询区块更高效,能实现近乎实时的交易推送。
替代方案:日志关键词过滤
可直接监听包含Swap关键词的全网交易日志,快速筛选swap操作:
async function subscribeToAllSwapLogs() { const subscriptionId = connection.onLogs( '', async (logEntry, context) => { if (logEntry.logs?.some(line => line.includes('Swap'))) { const swapRecord = await parseSwapTransaction(logEntry); if (swapRecord) { console.log('全网购买交易记录:', swapRecord); } } }, 'confirmed' ); }
注意事项
- 交易指令结构可能随DEX版本更新,需及时同步解析逻辑。
- 代币数量为大数字,需用
BigInt处理避免精度丢失。 - 主网交易量大,需做好错误捕获和资源控制,防止程序崩溃。
内容的提问来源于stack exchange,提问作者Deimantas Maksele
相关产品推荐
相关产品推荐

