Solana 上如何获取Token 所有持有者

  • Sola
  • 更新于 2024-02-26 22:11
  • 阅读 892

理解 Solana 账户模型,获取 Token 所有持有者

在本指南中,我们将看看如何获取诸如 USDC 之类的同质化Token的所有持有者。这在你想要跟踪Token持有者或奖励持有者进行空投的情况下非常有用。

概述

让我们首先看看Token,特别是在 Solana 上如何工作。当开发人员创建一个Token时,他们使用Token程序(Token Program)来创建一个铸造账户。这个铸造账户保存了关于特定 Token 的信息,比如名称、Token地址和图像。一旦铸造账户被创建,Token 就可以被铸造并存储在一个 Token 账户中。Token账户是一个账户,保存了关于特定Token的信息,由特定地址拥有。Token账户将包括铸造地址(对应下图的Token Address)、所有者地址以及账户中特定Token的数量等细节。例如,持有一些 USDC(一个 SPL Token )的地址将拥有一个 USDC 的Token账户。

65d59a8c5f6bee1516ab8758_tokenholders-diagram.jpeg

账户分解图

‍ 现在我们了解了Token和Token账户的工作原理,我们可以看看如何获取给定Token的所有Token持有者。持有特定Token的每个钱包都将拥有该 Token的Token账户。这意味着 Token 与持有该Token 钱包的 Token账户 相关联。这就是我们将找出所有持有者的方式。如果我们能找到一种方法来获取与一个Token相关联的所有Token账户,然后获取这些账户的所有者,我们将得到一个所有持有者的列表!

译者备注:与以太坊不同,在以太坊中用户的Token余额保存在 Token合约中,在 Solana 中,每个钱包账号持有的余额单独保存的 Token 账户。在 Solana 中甚至没有单独的Token合约, 而是使用Token 的铸造地址来区分不同的 Token。

getTokenAccounts 方法

幸运的是,Helius getTokenAccounts API 方法允许我们精确地做到这一点。我们可以在 API 调用参数中包含任何Token的铸造地址,我们将得到一个包含为该Token创建的所有Token账户的列表。除此之外,API 还返回每个Token账户的所有者;这个所有者通常被我们称为Token持有者。需要注意的一件小事是,一个账户可以拥有同一个Token的多个Token账户。这不是一个大问题;我们只需要设置一些逻辑来处理共享所有者的Token账户。

实现

现在让我们深入一些代码,看看我们实际上如何做到这一点。你需要一个 Helius API 密钥才能跟随。你可以通过访问 https://dev.helius.xyz 注册一个免费账户来获取一个。首先,我们必须创建一个名为getTokenHolders.js的 Javascript 文件。我们可以通过添加我们的 Helius URL 并导入 fs 库来将我们的结果保存到一个JSON文件中。

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

接下来,我们将创建一个方法来获取与特定Token相关联的所有Token账户。我们可以通过创建一个名为 findHolders 的方法来开始,该方法将使用 getTokenAccounts 方法来获取所需的数据。你可以在这里了解更多关于getTokenAccounts方法的信息。需要注意的一件重要的事情是,每次对 API 的调用只能返回最多 1000 个Token账户。Solana 上的大多数大型Token都有超过 100,000 个Token账户。为了解决这个问题,我们将使用分页来浏览所有Token账户,并继续进行 API 调用,直到我们获取了所有现有Token账户的数据。在这个方法中,我们将在getTokenAccounts调用的参数中包含Token铸造账号。当我们遍历所有Token账户时,我们将把每个唯一的Token账户所有者添加到一个列表中。一旦方法运行完成,我们将把这个列表保存到一个包含所有Token持有者的JSON文件中。

const findHolders = async () => {
  // Pagination logic
  let page = 1;
    // allOwners will store all the addresses that hold the token
  let allOwners = new 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: {},
                    //我们关注的token 铸币地址
          mint: "CKfatsPMUf8SkiURsDXs7eK6GWb4Jsd6UDbs7twMCWxo",
        },
      }),
    });
    const data = await response.json();
    // Pagination logic. 
    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}`);
        // Adding unique owners to a list of token owners. 
    data.result.token_accounts.forEach((account) =>
      allOwners.add(account.owner)
    );
    page++;
  }

  fs.writeFileSync(
    "output.json",
    JSON.stringify(Array.from(allOwners), null, 2)
  );
};

Copy

在上面的示例中,getTokenAccounts方法在分页浏览所有Token账户时被多次调用。API 响应将为每个Token账户提供以下数据:

{
"address": "CVMR1nbxTcQ7Jpa1p137t5TyKFii3Y7Vazt9fFct3tk9",
"mint": "SHDWyBxihqiCj6YekG2GUr7wqKLeLAMK1gHZck9pL6y",
"owner": "CckxW6C1CjsxYcXSiDbk7NYfPLhfqAm3kSB5LEZunnSE",
"amount": 100000000,
"delegated_amount": 0,
"frozen": false
},

我们从这些 Token 账户中提取了所有者,并将其添加到我们的列表中。如果我们愿意,我们还可以存储每个Token账户持有的Token数量,以找出最大的持有者。

现在一旦这个操作完成,我们需要做的就是调用这个方法:

findHolders();

我们的getTokenHolders.js文件中的完整代码应该如下所示:

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

const findHolders = async () => {
  let page = 1;
  let allOwners = new 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: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
        },
      }),
    });
    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++;
  }

  fs.writeFileSync(
    "output.json",
    JSON.stringify(Array.from(allOwners), null, 2)
  );
};

findHolders();

输出

我们代码的输出将是所有持有者的列表,看起来类似于这样:

[
 "111An9SVxuPpgjnuXW9Ub7hcVmZpYNrYZF4edsGwJEW",
 "11Mmng3DoMsq2Roq8LBcqdz6d4kw9oSD8oka9Pwfbj",
 "112uNfcC8iwX9P2TkRdJKyPatg6a4GNcr9NC5mTc2z3",
 "113uswn5HNgEfBUKfK4gVBmd2GpZYbxd1N6h1uUWReg",
 "11CyvpdYTqFmCVWbJJeKFNX8F8RSjNSYW5VVUi8eX4P",
 "11MANeaiHEy9S9pRQNu3nqKa2gpajzX2wrRJqWrf8dQ",
…
]

你可以通过我们的 replit 示例来测试这一点。

结论

总结以下,我们成功地介绍了通过 Helius getTokenAccounts API 来识别 Solana Token持有者的过程。这个步骤应该为你提供必要的技能,直接与你的Token社区进行互动。

原文:https://www.helius.dev/blog/how-to-get-token-holders-on-solana

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Sola
Sola
江湖只有他的大名,没有他的介绍。