Parameters

mint
string
required
Public key of the token mint (base-58 encoded)
config
object
Configuration object containing:
limit
number
Maximum number of accounts to return (default: 20)
commitment
string
Commitment level (processed, confirmed, finalized)

Response

result
object
Object containing:
context
object
slot
number
The slot the request was processed at
value
array
Array of token account objects containing:
address
string
Public key of the token account (base-58 encoded)
amount
string
Raw amount of tokens as a string
decimals
number
Number of decimals configured for token’s mint
uiAmount
number
Token amount as a float, accounting for decimals
uiAmountString
string
Token amount as a string, accounting for decimals

Code Examples

Basic Request

curl https://rpc.orbitflare.com -X POST -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "getTokenLargestAccounts",
  "params": [
    "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    {
      "limit": 10
    }
  ]
}'

Using web3.js

import { Connection, PublicKey } from '@solana/web3.js';

const connection = new Connection('https://rpc.orbitflare.com');

// 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
      }
    }
  };
}

Notes

  1. Returns the largest token accounts for a given mint
  2. Accounts are sorted by balance in descending order
  3. The response is immediate as it reads from the current state
  4. The accounts can change with token transfers and other operations
  5. The mint must be a valid token mint

Best Practices

  1. Use appropriate commitment level based on your needs
  2. Cache results when appropriate to reduce RPC load
  3. Monitor for changes in largest accounts
  4. Consider using websocket subscription for real-time updates
  5. Handle network errors and retry when appropriate

Common Errors

CodeMessageSolution
-32601Method not foundVerify you’re connected to a Solana RPC node
-32602Invalid paramsCheck mint public key and configuration
-32007Mint not foundVerify the mint exists
-32008Invalid limitEnsure limit is a positive number

Use Cases

  1. Token Distribution Analysis
    interface TokenDistributionAnalysis {
      mint: string;
      accounts: Array<{
        address: string;
        amount: string;
        percentage: number;
        rank: number;
      }>;
      metrics: {
        totalAccounts: number;
        totalSupply: string;
        concentration: number; // Gini coefficient
        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
          }
        };
      }
    }
    
  2. Token Holder Monitoring
    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;
        }> = [];
        
        // Check for removed or modified holders
        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
              });
            }
          }
        });
        
        // Check for added holders
        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;
      }
    }
    
  3. Token Supply Planning
    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; // Maximum allowed concentration
      private readonly minHolders = 100; // Minimum number of holders
      
      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;
        }> = [];
        
        // Check for concentration
        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`
          });
        }
        
        // Check for minimum holders
        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()
          }
        };
      }
    }