参数
代币铸造的公钥(base-58 编码)
响应
代码示例
基本请求
复制
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getTokenLargestAccounts",
"params": [
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
{
"limit": 10
}
]
}'
使用 web3.js
复制
import { Connection, PublicKey } from '@solana/web3.js';
const connection = new Connection('https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY');
// Get largest token accounts
const mint = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
const accounts = await connection.getTokenLargestAccounts(mint, { limit: 10 });
console.log('Largest token accounts:', accounts);
// Get largest token accounts with analysis
async function getTokenLargestAccountsWithAnalysis(
mint: PublicKey,
config: { limit?: number; commitment?: string }
) {
const accounts = await connection.getTokenLargestAccounts(mint, config);
return {
accounts,
analysis: {
totalAccounts: accounts.value.length,
totalSupply: accounts.value.reduce((sum, acc) => {
const amount = BigInt(acc.amount);
return sum + amount;
}, BigInt(0)),
distribution: accounts.value.reduce((acc, account, index) => {
const amount = BigInt(account.amount);
const percentage = Number((amount * BigInt(100)) / BigInt(accounts.value[0].amount));
acc[account.address] = {
amount: account.amount,
percentage,
rank: index + 1
};
return acc;
}, {} as Record<string, {
amount: string;
percentage: number;
rank: number;
}>),
metadata: {
timestamp: Date.now(),
commitment: config.commitment
}
}
};
}
注意事项
- 返回给定铸造的最大代币账户
- 账户按余额降序排序
- 响应是即时的,因为它从当前状态读取
- 账户可能随代币转账和其他操作而变化
- 铸造必须是有效的代币铸造
最佳实践
- 根据需求使用适当的 commitment 级别
- 在适当时缓存结果以减少 RPC 负载
- 监控最大账户的变化
- 考虑使用 WebSocket 订阅获取实时更新
- 适当处理网络错误并重试
常见错误
| 错误码 | 消息 | 解决方案 |
|---|---|---|
| -32601 | Method not found | 验证是否连接到 Solana RPC 节点 |
| -32602 | Invalid params | 检查铸造公钥和配置 |
| -32007 | Mint not found | 验证铸造是否存在 |
| -32008 | Invalid limit | 确保限制是正数 |
用例
-
代币分布分析
复制
interface TokenDistributionAnalysis { mint: string; accounts: Array<{ address: string; amount: string; percentage: number; rank: number; }>; metrics: { totalAccounts: number; totalSupply: string; concentration: number; top10Percentage: number; }; metadata: { timestamp: number; commitment?: string; }; } class TokenDistributionAnalyzer { private calculateGiniCoefficient(amounts: bigint[]): number { const n = amounts.length; const mean = amounts.reduce((sum, x) => sum + x, BigInt(0)) / BigInt(n); let numerator = BigInt(0); let denominator = BigInt(0); for (let i = 0; i < n; i++) { for (let j = 0; j < n; j++) { numerator += (amounts[i] - amounts[j]).abs(); } denominator += amounts[i]; } return Number(numerator) / (2 * n * Number(denominator)); } async analyzeTokenDistribution( mint: PublicKey, config: { limit?: number; commitment?: string } ): Promise<TokenDistributionAnalysis> { const accounts = await connection.getTokenLargestAccounts(mint, config); const amounts = accounts.value.map(acc => BigInt(acc.amount)); const totalSupply = amounts.reduce((sum, x) => sum + x, BigInt(0)); const top10Supply = amounts.slice(0, 10).reduce((sum, x) => sum + x, BigInt(0)); return { mint: mint.toBase58(), accounts: accounts.value.map((account, index) => ({ address: account.address, amount: account.amount, percentage: Number((BigInt(account.amount) * BigInt(100)) / totalSupply), rank: index + 1 })), metrics: { totalAccounts: accounts.value.length, totalSupply: totalSupply.toString(), concentration: this.calculateGiniCoefficient(amounts), top10Percentage: Number((top10Supply * BigInt(100)) / totalSupply) }, metadata: { timestamp: Date.now(), commitment: config.commitment } }; } } -
代币持有者监控
复制
interface TokenHolderChange { mint: string; changes: Array<{ type: 'added' | 'removed' | 'modified'; address: string; previousAmount?: string; currentAmount?: string; previousRank?: number; currentRank?: number; }>; metadata: { timestamp: number; }; } class TokenHolderMonitor { private previousHolders: Map<string, { amount: string; rank: number; }> = new Map(); async monitorTokenHolders( mint: PublicKey, config: { limit?: number; commitment?: string } ): Promise<TokenHolderChange | null> { const accounts = await connection.getTokenLargestAccounts(mint, config); const currentHolders = new Map( accounts.value.map((account, index) => [ account.address, { amount: account.amount, rank: index + 1 } ]) ); const changes: Array<{ type: 'added' | 'removed' | 'modified'; address: string; previousAmount?: string; currentAmount?: string; previousRank?: number; currentRank?: number; }> = []; this.previousHolders.forEach((data, address) => { if (!currentHolders.has(address)) { changes.push({ type: 'removed', address, previousAmount: data.amount, previousRank: data.rank }); } else { const current = currentHolders.get(address)!; if (current.amount !== data.amount || current.rank !== data.rank) { changes.push({ type: 'modified', address, previousAmount: data.amount, currentAmount: current.amount, previousRank: data.rank, currentRank: current.rank }); } } }); currentHolders.forEach((data, address) => { if (!this.previousHolders.has(address)) { changes.push({ type: 'added', address, currentAmount: data.amount, currentRank: data.rank }); } }); this.previousHolders = currentHolders; if (changes.length > 0) { return { mint: mint.toBase58(), changes, metadata: { timestamp: Date.now() } }; } return null; } } -
代币供应规划
复制
interface TokenSupplyPlan { mint: string; currentHolders: Array<{ address: string; amount: string; rank: number; }>; recommendations: Array<{ type: 'diversify' | 'consolidate' | 'rebalance'; addresses: string[]; reason: string; }>; metadata: { timestamp: number; }; } class TokenSupplyPlanner { private readonly maxConcentration = 0.5; private readonly minHolders = 100; async planTokenSupply( mint: PublicKey, config: { limit?: number; commitment?: string } ): Promise<TokenSupplyPlan> { const accounts = await connection.getTokenLargestAccounts(mint, config); const amounts = accounts.value.map(acc => BigInt(acc.amount)); const totalSupply = amounts.reduce((sum, x) => sum + x, BigInt(0)); const recommendations: Array<{ type: 'diversify' | 'consolidate' | 'rebalance'; addresses: string[]; reason: string; }> = []; const top10Supply = amounts.slice(0, 10).reduce((sum, x) => sum + x, BigInt(0)); const concentration = Number((top10Supply * BigInt(100)) / totalSupply) / 100; if (concentration > this.maxConcentration) { recommendations.push({ type: 'diversify', addresses: accounts.value.slice(0, 10).map(acc => acc.address), reason: `Top 10 holders control ${(concentration * 100).toFixed(2)}% of supply` }); } if (accounts.value.length < this.minHolders) { recommendations.push({ type: 'diversify', addresses: accounts.value.map(acc => acc.address), reason: `Only ${accounts.value.length} holders, below minimum of ${this.minHolders}` }); } return { mint: mint.toBase58(), currentHolders: accounts.value.map((account, index) => ({ address: account.address, amount: account.amount, rank: index + 1 })), recommendations, metadata: { timestamp: Date.now() } }; } }