From e9fe23f85a9c7b3e01f3047ea0c87ed333f1525f Mon Sep 17 00:00:00 2001 From: easyplux Date: Fri, 10 Jan 2025 22:25:15 +0800 Subject: [PATCH] Added token Holders analysis --- example-04-analysisToken/README.md | 125 ++++++++++++++++++++++++++ example-04-analysisToken/index.ts | 140 +++++++++++++++++++++++++++++ 2 files changed, 265 insertions(+) create mode 100644 example-04-analysisToken/README.md create mode 100644 example-04-analysisToken/index.ts diff --git a/example-04-analysisToken/README.md b/example-04-analysisToken/README.md new file mode 100644 index 0000000..21cf4dd --- /dev/null +++ b/example-04-analysisToken/README.md @@ -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 + +``` \ No newline at end of file diff --git a/example-04-analysisToken/index.ts b/example-04-analysisToken/index.ts new file mode 100644 index 0000000..bc339e8 --- /dev/null +++ b/example-04-analysisToken/index.ts @@ -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();