Skip to content

Commit

Permalink
Added token Holders analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
EasyChris committed Jan 10, 2025
1 parent 009fa50 commit e9fe23f
Show file tree
Hide file tree
Showing 2 changed files with 265 additions and 0 deletions.
125 changes: 125 additions & 0 deletions example-04-analysisToken/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
## 分析token持有者

通过 `getParsedProgramAccounts` 查询所有代币账户,然后根据 `mint` 地址过滤出持有该代币的账户。

这样就可以构建一个简单的 token 持有者列表,同时对 token 的持仓进行一个分析。

分析结果如下:

```
前10大持有者分析:
==================================================
1. 地址: 5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1
持仓量: 345,412,370.048
占比: 34.55%
2. 地址: D6kyD96Tfkz5fA8JYhWkRPCdJxJ1dAk2ALpchjyUxApu
持仓量: 35,007,630.972
占比: 3.50%
3. 地址: ALCzpmL4jHVQNooT8PrxjiFDU5YYynVDqLam5FrPgn7b
持仓量: 33,554,743.151
占比: 3.36%
4. 地址: APUnpSv4HDpNPfed4dPqAnz75REWYbM5vTHaTnApLe1P
持仓量: 24,850,304.554
占比: 2.49%
5. 地址: 6xBTJa2VzLUnZnSPbvaTNKGYMoxG4Pm3d6B6nsPVbWUU
持仓量: 23,736,153.23
占比: 2.37%
6. 地址: GR3a6esWvmcE33LqwW1FgQEy7E6Mq8cE2uEWXc4VtcsK
持仓量: 21,725,403.233
占比: 2.17%
7. 地址: 2dM6wMKS2is3jpwMueXvLfCgwveMiwB1iQNowkjx3x8S
持仓量: 20,923,943.722
占比: 2.09%
8. 地址: FFL94Rd9ZBorakrH7okwHNMrhiWwK6WT53PazjATW2zg
持仓量: 18,385,694.794
占比: 1.84%
9. 地址: 5aXGUFvh2v5wFzYAsfMsX7YLEpFw4uPQza9UatRZnL4c
持仓量: 16,428,619.503
占比: 1.64%
10. 地址: Cw4vsaQ9JpeS4CRn66KmF5oRazo6C7AwMk1BSVYTMjQR
持仓量: 16,397,086.408
占比: 1.64%
代币持仓分布分析报告:
==================================================
总供应量: 999,837,357.511
总持有者: 7,101
==================================================
持仓区间: 1-100
持有者数量: 402 (5.66%)
持仓总量: 4,136.054 (0.00%)
平均持仓: 10.29
主要持有者:
- 4xr8U1TMkKHi7H2BC2dYVv3yXnUkeUphvmauK541SRsX
- 8GbasKKd4yHH83CvS4mCuMEJvLemSrrV7De5hmNQ59Hb
- F9Br3tp1kKqNuXSZgFMvevWocn8YyX5H89g76cCBqiv
- PCnb69Pi1T8DkxMBQahtteRZ9QdC5QbQS44DeUDaDum
- 2a2NqsUWFR8eFaXNkhhuFSpVkTbctGao9ZZvbkLGcrEm
持仓区间: 101-1,000
持有者数量: 83 (1.17%)
持仓总量: 47,501.135 (0.00%)
平均持仓: 572.30
主要持有者:
- 79P6UsqG1Y2cB2xcmKcaCoBn3Gba44ACVgS9xmQFULs7
- C7VDfuACjqoT6rckWusPk8NSy6JmvYgcGmu4w6p7V3yx
- Axd1HqUHxxW1peeGEwNmeckxuNATDJFeeEEMsmkJ6gGn
- AqSR8UrBUG2dsT4LRMF9ceSayXu8oMXxfXc1FZbpHcbp
- DoiUTaHyuEsMFQGanitoSScdEh78AWGpuNe5i1jp3Xdd
持仓区间: 1,001-10,000
持有者数量: 274 (3.86%)
持仓总量: 1,193,665.167 (0.12%)
平均持仓: 4356.44
主要持有者:
- 35tj37dCmiLxTV4cLRwXq6ycEhUqzG25PMaz4akMCHzV
- 9vPVcvWomyDirhif6TeAa1tLPi5DkznFHmNsLHb6BWkf
- 7APv2exT4QyhEHkDyEwY4TJR3pCSQPc7T3P9ZPA6sQNG
- EfB3Q81JNNXuRsHt6gDN8L1CEqCuj5Gxgwgruj8bJdDi
- Ci4s3nrWuhQriwgpEHwB8tUbzsx724bqugo5snHYJR7u
持仓区间: 10,001-100,000
持有者数量: 333 (4.69%)
持仓总量: 12,212,409.527 (1.22%)
平均持仓: 36673.90
主要持有者:
- HKtfKesi64ubxkoBkkDEvgEtXAEmwprtwbxgSxyDQXqN
- An2vTG4AgYTtK7ED9qF6RaLsSmVRoe5QSxrke441wrjN
- HwmkZo36DMvbRjsereuLmGFBdeJPSFKgfVWf6jUZd76Y
- Et1M87kKDLpxMywjVKoFUusBFEW7rQzSKsffTCvgqBxd
- EZgyr2aZESMvgzSfa2JjxjKrRCeYe2uc7YHTLt1eEKMM
持仓区间: 100,001-1,000,000
持有者数量: 209 (2.94%)
持仓总量: 69,417,348.63 (6.94%)
平均持仓: 332140.42
主要持有者:
- 4EKUCa6YCDwjHS5giQ4DJpvdyZ4XoRsmDZNSPwPgScwC
- HkhCAiPabzFmUiHQAASg7rYiHthJ4sqGH5ygHHVhWsRf
- T2ESjZiPmv7Fb2rAWebLpYnyTa8yyVCWaGMot7DpGjG
- EpmSLKSnwZxpXzQkE76woiCTF6UkFmjAsSWpovANVMRy
- 973rVqBCtaExEVGvEoYqyJta6THeXCC9pCRZuPoEUCMc
持仓区间: 1,000,000+
持有者数量: 83 (1.17%)
持仓总量: 916,962,296.997 (91.71%)
平均持仓: 11047738.52
主要持有者:
- 5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1
- D6kyD96Tfkz5fA8JYhWkRPCdJxJ1dAk2ALpchjyUxApu
- ALCzpmL4jHVQNooT8PrxjiFDU5YYynVDqLam5FrPgn7b
- APUnpSv4HDpNPfed4dPqAnz75REWYbM5vTHaTnApLe1P
- 6xBTJa2VzLUnZnSPbvaTNKGYMoxG4Pm3d6B6nsPVbWUU
```
140 changes: 140 additions & 0 deletions example-04-analysisToken/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { Connection, PublicKey, ParsedAccountData } from "@solana/web3.js";

const connection = new Connection("https://api.mainnet-beta.solana.com", "confirmed");

async function getTokenHolders(mintAddress: string) {
// 1. 参数说明:mintAddress 是代币的 Mint 地址
// 例如:USDC 的 Mint 地址是 "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
const mint = new PublicKey(mintAddress);

// 2. 调用 getParsedProgramAccounts 查询所有代币账户
const accounts = await connection.getParsedProgramAccounts(
// Token 程序的地址(固定值)
new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'),
{
filters: [
// Token 账户的大小固定为 165 字节
{ dataSize: 165 },
{
// 在数据开始位置匹配 Mint 地址
memcmp: {
offset: 0,
bytes: mint.toBase58(),
},
},
],
}
);

// 3. 处理返回数据
const holders = accounts.map(account => ({
// 代币账户地址
address: account.pubkey.toString(),
// 代币余额(已考虑小数位)
amount: (account.account.data as ParsedAccountData).parsed.info.tokenAmount.uiAmount,
// 代币账户所有者(钱包地址)
owner: (account.account.data as ParsedAccountData).parsed.info.owner
}));

// 4. 按持有量从大到小排序
return holders.sort((a, b) => b.amount - a.amount);
}

interface TokenDistribution {
range: string;
holders: number;
totalAmount: number;
percentage: string;
addresses: string[];
}

async function getTokenDistribution(holders: any[]) {
// 计算总供应量
const totalSupply = holders.reduce((sum, h) => sum + Number(h.amount), 0);

// 定义分布区间(可以根据需要调整)
const ranges = [
{ min: 0, max: 100, label: "1-100" },
{ min: 100, max: 1000, label: "101-1,000" },
{ min: 1000, max: 10000, label: "1,001-10,000" },
{ min: 10000, max: 100000, label: "10,001-100,000" },
{ min: 100000, max: 1000000, label: "100,001-1,000,000" },
{ min: 1000000, max: Infinity, label: "1,000,000+" }
];

// 初始化结果
const distribution: { [key: string]: TokenDistribution } = {};
ranges.forEach(range => {
distribution[range.label] = {
range: range.label,
holders: 0,
totalAmount: 0,
percentage: "0%",
addresses: []
};
});

// 统计分布
holders.forEach(holder => {
const amount = Number(holder.amount);
const range = ranges.find(r => amount > r.min && amount <= r.max);
if (range) {
const label = range.label;
distribution[label].holders++;
distribution[label].totalAmount += amount;
distribution[label].addresses.push(holder.owner);
}
});

// 计算百分比
Object.values(distribution).forEach(d => {
d.percentage = ((Number(d.totalAmount) / Number(totalSupply)) * 100).toFixed(2) + '%';
});

// 生成报告
console.log("\n代币持仓分布分析报告:");
console.log("=".repeat(50));
console.log(`总供应量: ${totalSupply.toLocaleString()}`);
console.log(`总持有者: ${holders.length.toLocaleString()}`);
console.log("=".repeat(50));

Object.values(distribution).forEach(d => {
if (d.holders > 0) {
console.log(`\n持仓区间: ${d.range}`);
console.log(`持有者数量: ${d.holders.toLocaleString()} (${((d.holders/holders.length)*100).toFixed(2)}%)`);
console.log(`持仓总量: ${d.totalAmount.toLocaleString()} (${d.percentage})`);
console.log(`平均持仓: ${(Number(d.totalAmount)/Number(d.holders)).toFixed(2)}`);

// 只显示前5个大户地址
if (d.addresses.length > 0) {
console.log("主要持有者: ");
d.addresses.slice(0, 5).forEach(addr =>
console.log(` - ${addr}`)
);
}
}
});

return distribution;
}



async function main() {
const holders = await getTokenHolders("Dp4fXozKtwgK1cL5KQeeNbuAgFpJtY3FbAvL8JrWpump");
// 计算总供应量
const totalSupply = holders.reduce((sum, h) => sum + Number(h.amount), 0);

const topHolders = holders.slice(0, 10); // 前10大持有者
console.log("\n前10大持有者分析:");
console.log("=".repeat(50));
topHolders.forEach((holder, index) => {
console.log(`${index + 1}. 地址: ${holder.owner}`);
console.log(` 持仓量: ${Number(holder.amount).toLocaleString()}`);
console.log(` 占比: ${((Number(holder.amount) / Number(totalSupply)) * 100).toFixed(2)}%\n`);
});

await getTokenDistribution(holders)
}

main();

0 comments on commit e9fe23f

Please sign in to comment.