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()
          }
        };
      }
    }