如何获取 Solana 代币持有者列表的完整指南

·

在 Solana 区块链生态中,获取特定代币(如 USDC)的所有持有者信息是一项常见需求,无论是用于空投奖励、数据分析还是社区管理。本文将详细介绍如何利用专业工具高效获取这些信息。

Solana 代币与代币账户的基本原理

在深入技术细节之前,我们首先需要理解 Solana 上代币的基本运作方式。

代币的创建与存储

当开发者在 Solana 上创建一个代币时,他们会通过 Token Program 创建一个 Mint 账户。这个 Mint 账户包含了该代币的元数据,例如其名称、代币地址和图标。

代币被铸造出来后,会被存储在一个 Token 账户中。每个 Token 账户都关联着一个特定的钱包地址和一个特定的 Mint 账户,它记录了该地址持有该代币的数量。例如,一个持有 USDC(一种 SPL 代币)的钱包,就会拥有一个专门用于存储 USDC 的 Token 账户。

持有者信息的关联逻辑

每一个持有特定代币的钱包都会拥有一个对应的 Token 账户。因此,要获取该代币的所有持有者列表,本质上就是找到所有关联了该代币 Mint 地址的 Token 账户,并提取出这些账户的所有者地址。

使用 getTokenAccounts API 方法获取持有者

幸运的是,Helius 提供的 getTokenAccounts API 方法能够完美地实现这一目标。该方法允许我们通过传入代币的 Mint 地址,获取到所有为该代币创建的 Token 账户的列表。更重要的是,API 的返回值中直接包含了每个 Token 账户的所有者地址,即我们所要寻找的代币持有者。

需要注意的是,一个钱包地址可以为同一个代币创建多个 Token 账户。在数据处理时,我们需要通过逻辑判断来对持有者进行去重,以确保列表的准确性。

具体实现步骤与代码解析

下面我们将通过一个具体的代码示例,演示如何一步步地获取并保存代币持有者列表。

准备工作

在开始之前,你需要一个 Helius 的 API 密钥。你可以访问其官方网站免费注册并获取。接下来,我们创建一个名为 getTokenHolders.js 的 JavaScript 文件。

初始化设置

首先,我们引入必要的模块并配置 API 请求的 URL。

const url = `https://mainnet.helius-rpc.com/?api-key=你的API密钥`;
const fs = require("fs");

核心方法:遍历并获取持有者

由于 API 每次调用最多返回 1000 个 Token 账户,而对于像 USDC 这样的大型代币,其 Token 账户数量可能高达数十万,因此我们必须使用分页技术来遍历所有结果。

我们创建一个名为 findHolders 的异步函数来处理这个过程:

const findHolders = async () => {
  let page = 1;
  let allOwners = new Set(); // 使用 Set 自动处理重复地址

  while (true) {
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        jsonrpc: "2.0",
        method: "getTokenAccounts",
        id: "helius-test",
        params: {
          page: page,
          limit: 1000,
          displayOptions: {},
          mint: "这里替换为你的代币Mint地址", // 例如 USDC 的 Mint 地址
        },
      }),
    });

    // 错误处理
    if (!response.ok) {
      console.log(`Error: ${response.status}, ${response.statusText}`);
      break;
    }

    const data = await response.json();

    // 分页终止条件:当没有更多结果时退出循环
    if (!data.result || data.result.token_accounts.length === 0) {
      console.log(`No more results. Total pages: ${page - 1}`);
      break;
    }

    console.log(`Processing results from page ${page}`);
    // 提取并保存所有者地址
    data.result.token_accounts.forEach((account) => allOwners.add(account.owner));
    page++;
  }

  // 将最终结果写入 JSON 文件
  fs.writeFileSync("output.json", JSON.stringify(Array.from(allOwners), null, 2));
};

API 响应数据结构

API 返回的每个 Token 账户对象都包含以下关键信息:

执行并输出结果

最后,我们调用这个函数并运行脚本。

findHolders();

脚本运行完成后,所有唯一的持有者地址将被保存到当前目录下的 output.json 文件中。该文件是一个简单的 JSON 数组,格式如下:

[
  "111An9SVxuPpgjnuXW9Ub7hcVmZpYNrYZF4edsGwJEW",
  "11Mmng3DoMsq2Roq8LBcqdz6d4kw9oSD8oka9Pwfbj",
  "112uNfcC8iwX9P2TkRdJKyPatg6a4GNcr9NC5mTc2z3",
  ...
]

👉 查看实时链上数据工具

常见问题

什么是 Mint 地址?

Mint 地址是 Solana 区块链上代表一种特定代币的唯一标识符。它由创建该代币的 Token Program 生成,包含了代币的元信息,如总供应量、小数位数等。所有同质化代币(如 USDC)和非同质化代币(NFT)都有自己的 Mint 地址。

为什么需要使用分页(Pagination)?

由于大型代币的持有者数量可能极其庞大,一次性获取所有数据会超出 API 的单次响应限制,并且对服务器和客户端造成巨大压力。分页技术将数据拆分成多个小块(如每次1000条)进行请求,是处理大规模数据集的标准方法。

除了持有者列表,我还能获取哪些信息?

通过 getTokenAccounts API,你不仅可以获得持有者地址,还能获取每个 Token 账户的余额信息。这使你能够进一步分析持币分布,识别出巨鲸地址(持有大量代币的地址),这对于市场分析和社区运营非常有价值。

一个钱包地址会多次出现在列表中吗?

会的。如果一个用户为同一个代币创建了多个 Token 账户,那么该用户的地址会在列表中出现多次。这就是为什么我们在代码中使用 Set 数据结构来自动去重,确保最终列表中的每个地址都是唯一的。

这个方法适用于所有 SPL 代币吗?

是的。此方法基于 Solana 的代币标准(SPL),因此适用于任何在 Solana 上创建的 SPL 代币,包括同质化代币(如 USDC, SRM)和非同质化代币(NFT)。你只需要将代码中的 Mint 地址替换为你想要查询的代币地址即可。

总结

通过本指南,我们系统地讲解了在 Solana 上获取任何 SPL 代币持有者列表的完整流程。从理解代币账户的基础模型,到使用 Helius 的 getTokenAccounts API 进行分页数据抓取,最后将数据保存为结构化文件。这套方法为开发者进行空投、数据分析、社区治理等应用提供了坚实的技术基础。