Solana代币转账跟踪实现

本文介绍如何监控 Solana 上的 SPL 代币转账和关联代币账户(ATAs)。

Solana代币转账跟踪实现
一键发币: SUI | SOL | BNB | ETH | BASE | ARB | OP | POLYGON | AVAX | FTM | OK

跟踪 Solana 上的代币转账比在以太坊等区块链上更为复杂。在以太坊上,交易直接涉及钱包地址。而在 Solana 上:

  • 代币被发送到关联代币账户(ATAs),而不是直接发送到钱包地址。
  • 必须动态获取并监控与钱包相关的所有 ATAs 来追踪现有的代币。
  • 要检测首次发送的代币(创建新的 ATA),需要监控钱包地址以捕获ATA 创建事件

有一种两步方法可以解决这个问题:

  1. 监控所有现有的 ATAs 的余额变化。
  2. 监控钱包地址本身以检测新 ATA 的创建,并动态更新 ATA 列表。

本指南将解释如何使用 Solana 的工具和 API 高效地实现这样的系统。

1、Solana代币转账跟踪简介

对于有经验的开发者来说,Web3 开发仍然可能令人望而生畏。随着区块链项目的快速增长以及不同生态系统中的独特实现方式,很容易迷失在解决问题的正确方法中。一个看似简单的问题,比如跟踪代币转账,在不同的区块链上可能会有很大的差异。

例如,在以太坊上,监听由智能合约发出的事件来监控 ERC-20 代币的转账非常简单。开发者只需跟踪相关钱包地址即可。然而,在 Solana 上,这个过程要复杂得多。代币不会直接发送到钱包地址,而是发送到与该钱包关联的关联代币账户(ATA)。这可能会让开发者感到困惑,并导致他们在文档中花费大量时间寻找可行的解决方案。

最近,我遇到了一个问题,一位开发者想要构建一个警报系统,当任何代币被发送到 Solana 钱包时通知他们。这个问题突显了 Solana 架构的独特挑战之一,我意识到这是一个澄清如何实现此类系统的绝佳机会。

2、问题陈述

在 Solana 上跟踪代币转账并不像监控钱包地址那么简单。与以太坊不同,以太坊上的交易直接与钱包地址交互,Solana 使用**关联代币账户(ATAs)**来管理 SPL 代币。当代币被发送到钱包时:

  1. 代币被存入从钱包地址和代币的铸造地址派生出的 ATA 中。
  2. 钱包地址本身不直接参与交易,因此如果你只监控钱包地址,则无法看到这些交易。

这带来了几个挑战:

  • 你不能通过仅仅监听钱包地址来跟踪传入的交易。
  • 要检测代币转账,你需要知道代币的铸造地址并预先派生其 ATA。
  • 如果代币首次被发送到钱包,ATA 在交易过程中才会创建。

3、初始尝试和观察

一种常见的方法是派生并监控特定代币的 ATA。这种方法在你知道发送的代币时工作得很好,但在系统需要:

  • 动态处理任何代币发送到钱包。
  • 检测首次代币转账时创建的新 ATA。

这些限制促使我们需要一个更强大且动态的解决方案。

4、提出的解决方案

解决方案包括一种双管齐下的方法

  1. 监控与钱包相关的所有现有 ATAs,以追踪已知代币的余额变化。
  2. 监控钱包地址本身,以检测新的 ATA 创建事件,确保新收到的代币也能被追踪。

这种动态策略确保不会错过任何代币转账,无论是代币已经与钱包关联还是首次发送。

4.1 理解关联代币账户

要在 Solana 上跟踪代币转账,第一步是了解 ATAs 是如何工作的。每个代币都有一个独特的 ATA 对应于一个钱包,通过以下方式派生:

  • 钱包的公钥。
  • 代币的铸造地址。

ATA 确保每个代币存储在一个单独的账户中,使 Solana 能够高效地管理代币余额。

要为特定代币派生 ATA:

const { PublicKey } = require("@solana/web3.js");  
const { getAssociatedTokenAddress } = require("@solana/spl-token");
async function deriveATA(walletAddress, tokenMint) {  
  const walletPubkey = new PublicKey(walletAddress);  
  const tokenMintPubkey = new PublicKey(tokenMint);  const ata = await getAssociatedTokenAddress(tokenMintPubkey, walletPubkey);  
  console.log(`关联代币账户(ATA): ${ata.toString()}`);  
}

这种方法在追踪特定代币时效果很好,但需要提前知道代币的铸造地址。

4.2 动态获取所有现有的 ATAs

为了处理多种代币,系统需要动态获取与钱包相关的所有现有 ATAs。这可以通过使用 Solana 的 getTokenAccountsByOwner API 实现:

async function fetchATAs(walletAddress) {  
  const connection = new Connection("https://api.mainnet-beta.solana.com");  
  const walletPubkey = new PublicKey(walletAddress);
  const accounts = await connection.getTokenAccountsByOwner(walletPubkey, {  
    programId: new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"), // SPL Token Program ID  
  });  console.log("获取的 ATAs:", accounts.value.map((account) => account.pubkey.toString()));  
  return accounts.value.map((account) => account.pubkey.toString());  
}

此函数检索钱包的所有 ATAs 及其余额,为监控代币转账提供了基础。

4.3 监控现有的 ATAs

获取 ATAs 后,下一步是监控它们的余额变化:

async function monitorATAs(atas) {  
  const connection = new Connection("https://api.mainnet-beta.solana.com");
  atas.forEach((ata) => {  
    connection.onLogs(new PublicKey(ata), (logs) => {  
      console.log(`检测到 ATA 的交易: ${ata}`);  
      console.log("日志:", logs);  
    });  
  });  
}

这确保了任何发送到现有 ATA 的代币都能被检测到。

4.4 检测新的 ATA 创建

由于新的 ATAs 在代币首次发送到钱包时动态创建,因此必须监控钱包地址以捕获这些事件。onLogs 方法可以捕获交易日志中的新 ATA 创建。

async function monitorWallet(walletAddress) {  
  const connection = new Connection("https://api.mainnet-beta.solana.com");
  connection.onLogs(new PublicKey(walletAddress), async (logs) => {  
    console.log(`检测到钱包的交易: ${walletAddress}`);  
    console.log("日志:", logs);    if (logs.signature) {  
      const txDetails = await connection.getParsedTransaction(logs.signature);  
      console.log("交易详情:", txDetails);      // 检测 ATA 创建并刷新 ATA 列表  
      const instructions = txDetails.transaction.message.instructions;  
      for (const instruction of instructions) {  
        if (instruction.programId.toString() === "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA") {  
          console.log("检测到新的 ATA!");  
          const newATAs = await fetchATAs(walletAddress);  
          monitorATAs(newATAs); // 使用新的 ATAs 更新监控  
        }  
      }  
    }  
  });  
}

4.5 综合一切

通过结合这些方法,系统实现了全面覆盖:

  1. 获取所有现有的 ATAs 并监控它们。
  2. 监控钱包地址以检测新的 ATA 创建事件。
  3. 动态刷新监控的 ATAs 列表。
async function startMonitoring(walletAddress) {  
  const existingATAs = await fetchATAs(walletAddress);  
  monitorATAs(existingATAs);  
  monitorWallet(walletAddress);  
}
startMonitoring("YOUR_WALLET_PUBLIC_KEY");

5、结束语

在 Solana 上跟踪代币转账需要应对 ATAs 独特的架构。虽然不像在以太坊上那样简单,但结合 ATA 监控和钱包日志分析确保不会错过任何代币转账。这个解决方案是动态、强大且可扩展的,为开发者提供了一种可靠的方法来跟踪发送到钱包的任何代币


原文链接:Tracking Token Transfers on Solana: A Developer’s Guide

DefiPlot翻译整理,转载请标明出处

免责声明:本站资源仅用于学习目的,也不应被视为投资建议,读者在采取任何行动之前应自行研究并对自己的决定承担全部责任。
通过 NowPayments 打赏