
如何获取 Solana 上的代币持有者
本指南将介绍如何获取 USDC 等同质化代币的所有持有者。当你需要追踪某种代币的持有者或通过空投奖励他们时,这会非常有用。
概述
首先来看看代币,尤其是非同质化代币,在 Solana 上如何运作。开发者创建代币时,会使用代币程序创建一个铸币账户。该铸币账户包含特定代币的信息,例如名称、代币地址和图片。创建铸币账户后,就可以铸造代币,并将其存储在代币账户中。代币账户用于保存由特定地址拥有的某种代币的相关信息,包括铸币地址、所有者地址,以及账户中该代币的数量等。例如,持有一定数量 USDC(SPL 代币)的地址会有一个 USDC 代币账户。
了解代币和代币账户的运作方式后,我们就可以获取指定代币的所有持有者。每个持有特定代币的钱包都会拥有该代币的代币账户。这意味着,该代币会与所有持有它的钱包对应的代币账户相关联。我们将据此找出所有持有者。只要能够获取与该代币关联的全部代币账户,再获取这些账户的所有者,就能得到所有持有者的列表!
getTokenAccounts 方法
幸运的是,Helius getTokenAccounts API 方法正好可以做到这一点。我们可以在 API 调用参数中加入任意代币的铸币地址,从而获得为该代币创建的所有代币账户列表。此外,API 还会返回每个代币账户的所有者;这个所有者就是我们通常所说的代币持有者。需要注意的是,同一个账户可以拥有同一种代币的多个代币账户。这并不是什么大问题;我们只需添加一些逻辑,处理所有者相同的代币账户即可。
实现
现在来深入研究一些代码,看看具体如何实现。你需要一个 Helius API 密钥才能跟随本教程操作。前往你的 Helius 控制面板注册账户,即可免费获取。首先,我们需要创建一个名为 getTokenHolders.js 的 Javascript 文件。可以先添加 Helius URL,并导入 fs 库,以便将结果保存到 JSON 文件中。
const url = `https://mainnet.helius-rpc.com/?api-key=`;
const fs = require("fs");接下来,我们将创建一个方法,用于获取与特定代币关联的所有代币账户。首先创建一个名为 findHolders 的方法,它将使用 getTokenAccounts 方法获取所需数据。你可以在这里进一步了解 getTokenAccounts 方法。
需要特别注意的是,每次 API 调用最多只能返回 1000 个代币账户。Solana 上的大多数大型代币都有超过 100,000 个代币账户。为解决这一问题,我们将使用分页遍历所有代币账户,并持续调用 API,直到获取所有现有代币账户的相关数据。
在该方法中,我们会将代币的铸币地址加入 getTokenAccounts 调用的参数。遍历所有代币账户时,我们会将每个唯一的代币账户所有者添加到列表中。方法运行完毕后,我们会将该列表保存到一个包含该代币所有持有者的 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: {},
//mint address for the token we are interested in
mint: "CKfatsPMUf8SkiURsDXs7eK6GWb4Jsd6UDbs7twMCWxo",
},
}),
});
// Check if any error in the response
if (!response.ok) {
console.log(
`Error: ${response.status}, ${response.statusText}`
);
break;
}
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)
);
};在上面的示例中,分页遍历所有代币账户时,会多次调用 getTokenAccounts 方法。API 响应将为每个代币账户提供以下数据:
{
"address": "CVMR1nbxTcQ7Jpa1p137t5TyKFii3Y7Vazt9fFct3tk9",
"mint": "SHDWyBxihqiCj6YekG2GUr7wqKLeLAMK1gHZck9pL6y",
"owner": "CckxW6C1CjsxYcXSiDbk7NYfPLhfqAm3kSB5LEZunnSE",
"amount": 100000000,
"delegated_amount": 0,
"frozen": false
},我们从这些代币账户中提取所有者,并将其添加到列表中。如果需要,还可以存储每个代币账户持有的代币数量,从而找出持有量最大的持有者。
完成这些操作后,只需调用该方法:
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",
},
}),
});
// Check if any error in the response
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++;
}
fs.writeFileSync(
"output.json",
JSON.stringify(Array.from(allOwners), null, 2)
);
};
findHolders();输出
代码将输出所有持有者的列表,结果类似如下:
[
"111An9SVxuPpgjnuXW9Ub7hcVmZpYNrYZF4edsGwJEW",
"11Mmng3DoMsq2Roq8LBcqdz6d4kw9oSD8oka9Pwfbj",
"112uNfcC8iwX9P2TkRdJKyPatg6a4GNcr9NC5mTc2z3",
"113uswn5HNgEfBUKfK4gVBmd2GpZYbxd1N6h1uUWReg",
"11CyvpdYTqFmCVWbJJeKFNX8F8RSjNSYW5VVUi8eX4P",
"11MANeaiHEy9S9pRQNu3nqKa2gpajzX2wrRJqWrf8dQ",
…
]你可以通过我们的 replit 示例亲自测试。
总结
至此,我们已经完整介绍了如何通过 Helius getTokenAccounts API 识别 Solana 代币持有者。本教程将帮助你掌握直接与代币社区互动所需的技能,无论是进行空投、获取洞察,还是开展更多互动。如果有任何问题,欢迎通过 Twitter 或 Discord联系我们。
相关文章
订阅 Helius
及时了解 Solana 开发的最新动态,并在我们发布新内容时收到更新


