如何查询Solana代币持有者

一键发币: SUI | SOL | BNB | ETH | BASE | ARB | OP | POLYGON | AVAX | FTM | OK
在这份指南中,我们将探讨如何获取一种可替代代币(例如USDC)的所有持有者。这在你希望跟踪代币持有者或通过空投奖励持有者时非常有用。
1、概览
首先,让我们了解一下Solana上的代币,特别是非同质化代币的工作原理。
当开发者创建一个代币时,他们使用代币程序来创建一个铸币账户。这个铸币账户包含了特定代币的信息,如名称、代币地址和图像。一旦铸币账户被创建,代币就可以被铸造并存储在一个代币账户中。
代币账户是一个包含特定代币信息的账户,这些信息由特定地址拥有。这将包括铸币地址、所有者地址以及账户中的特定代币数量。例如,一个持有某些USDC(一个SPL代币)的地址将有一个USDC的代币账户。

现在我们已经了解了代币和代币账户的工作原理,我们可以查看给定代币的所有代币持有者。每个持有特定代币的钱包都会有一个该代币的代币账户。这意味着这个代币将与所有持有该代币的钱包的代币账户相关联。这就是我们将如何找出所有持有者的方式。如果我们能找到一种方法来获取与某个代币相关的所有代币账户,然后获取这些账户的所有者,我们就能得到一份所有持有者的列表!
2、getTokenAccounts 方法
幸运的是,Helius getTokenAccounts
API 方法允许我们精确地做到这一点。我们可以将任何代币的铸币地址包含在API调用的参数中,并将返回一个包含为该代币创建的所有代币账户的列表。
除此之外,API还会返回每个代币账户的所有者;这个所有者就是我们通常所说的代币持有者。需要注意的一点是,一个账户可以有多个相同代币的代币账户。这不是大问题;我们需要设置一些逻辑来处理共享所有者的代币账户。
3、代码实现
现在让我们深入代码,看看如何实际做到这一点。你需要一个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");
接下来,我们将创建一个方法来获取与特定代币关联的所有代币账户。我们可以通过创建一个名为findHolders的方法开始,该方法将使用getTokenAccounts
方法来获取所需的数据。您可以在此处了解更多关于getTokenAccounts
方法的信息这里。
需要注意的重要一点是,每次调用API只能返回最多1000个代币账户。Solana上大多数大型代币都有超过100,000个代币账户。为了绕过这个问题,我们将使用分页来遍历所有代币账户,并继续进行API调用直到获取到所有现有代币账户的相关数据。
在方法中,我们将把代币铸币地址包含在getTokenAccounts
调用的参数中。当我们遍历所有代币账户时,我们将每个唯一的代币账户所有者添加到一个列表中。一旦方法运行完毕,我们将把这个列表保存到一个JSON文件中,其中包含所有代币的持有者。
const findHolders = async () => {
// 分页逻辑
let page = 1;
// allOwners 将存储持有代币的所有地址
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: "CKfatsPMUf8SkiURsDXs7eK6GWb4Jsd6UDbs7twMCWxo",
},
}),
});
// 检查响应是否有错误
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(`没有更多结果。总页数:${page - 1}`);
break;
}
console.log(`处理第 ${page} 页的结果`);
// 添加唯一的代币持有者到列表中。
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",
},
}),
});
// 检查响应是否有错误
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(`没有更多结果。总页数:${page - 1}`);
break;
}
console.log(`处理第 ${page} 页的结果`);
data.result.token_accounts.forEach((account) =>
allOwners.add(account.owner)
);
page++;
}
fs.writeFileSync(
"output.json",
JSON.stringify(Array.from(allOwners), null, 2)
);
};
findHolders();
4、输出
我们代码的输出将是一个持有者的列表,类似于以下内容:
[
"111An9SVxuPpgjnuXW9Ub7hcVmZpYNrYZF4edsGwJEW",
"11Mmng3DoMsq2Roq8LBcqdz6d4kw9oSD8oka9Pwfbj",
"112uNfcC8iwX9P2TkRdJKyPatg6a4GNcr9NC5mTc2z3",
"113uswn5HNgEfBUKfK4gVBmd2GpZYbxd1N6h1uUWReg",
"11CyvpdYTqFmCVWbJJeKFNX8F8RSjNSYW5VVUi8eX4P",
"11MANeaiHEy9S9pRQNu3nqKa2gpajzX2wrRJqWrf8dQ",
...
]
你可以通过我们的replit示例自行测试此功能。
原文链接:How to Get Token Holders on Solana
DefiPlot翻译整理,转载请标明出处
免责声明:本站资源仅用于学习目的,也不应被视为投资建议,读者在采取任何行动之前应自行研究并对自己的决定承担全部责任。