Parameters

delegate
string
required

Public key of the delegate (base-58 encoded)

config
object
required

Configuration object containing:

programId
string
required

Public key of the token program (base-58 encoded)

commitment
string

Commitment level (processed, confirmed, finalized)

encoding
string

Encoding for account data (base58, base64, jsonParsed)

dataSlice
object
offset
number

Offset into account data

length
number

Length of data to return

Response

result
object

Object containing:

context
object
slot
number

The slot the request was processed at

value
array

Array of token account objects containing:

pubkey
string

Public key of the token account (base-58 encoded)

account
object
lamports
number

Number of lamports in the account

owner
string

Public key of the account owner (base-58 encoded)

executable
boolean

Whether the account is executable

rentEpoch
number

Epoch at which the account will next owe rent

data
object
parsed
object
info
object
tokenAmount
object
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

mint
string

Public key of the token’s mint (base-58 encoded)

owner
string

Public key of the token account owner (base-58 encoded)

delegate
string

Public key of the delegate (base-58 encoded)

type
string

Type of account (account)

program
string

Program that owns the account (spl-token)

space
number

Number of bytes allocated to the account

Code Examples

Basic Request

curl https://rpc.orbitflare.com -X POST -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "getTokenAccountsByDelegate",
  "params": [
    "4vJ9JU1bJJE96FWSJKvHsmmFADCg4gpZQff4P3bkLZj",
    {
      "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
    }
  ]
}'

Using web3.js

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

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

// Get token accounts by delegate
const delegate = new PublicKey('4vJ9JU1bJJE96FWSJKvHsmmFADCg4gpZQff4P3bkLZj');
const programId = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
const accounts = await connection.getTokenAccountsByDelegate(delegate, { programId });
console.log('Token accounts:', accounts);

// Get token accounts by delegate with analysis
async function getTokenAccountsByDelegateWithAnalysis(
  delegate: PublicKey,
  config: { programId: PublicKey; commitment?: string }
) {
  const accounts = await connection.getTokenAccountsByDelegate(delegate, config);
  
  return {
    accounts,
    analysis: {
      totalAccounts: accounts.value.length,
      totalBalance: accounts.value.reduce((sum, acc) => {
        const amount = BigInt(acc.account.data.parsed.info.tokenAmount.amount);
        return sum + amount;
      }, BigInt(0)),
      byMint: accounts.value.reduce((acc, account) => {
        const mint = account.account.data.parsed.info.mint;
        const amount = BigInt(account.account.data.parsed.info.tokenAmount.amount);
        acc[mint] = (acc[mint] || BigInt(0)) + amount;
        return acc;
      }, {} as Record<string, bigint>),
      metadata: {
        timestamp: Date.now(),
        commitment: config.commitment
      }
    }
  };
}

Notes

  1. Returns all token accounts where the given public key is a delegate
  2. The delegate has the authority to transfer tokens from these accounts
  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 delegate must be a valid public key

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 delegated 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 delegate public key and configuration
-32007Delegate not foundVerify the delegate exists
-32008Invalid program IDVerify the program ID is correct

Use Cases

  1. Delegate Account Analysis

    interface DelegateAccountAnalysis {
      delegate: string;
      accounts: Array<{
        pubkey: string;
        mint: string;
        balance: string;
        owner: string;
      }>;
      metrics: {
        totalAccounts: number;
        totalBalance: string;
        byMint: Record<string, string>;
        byOwner: Record<string, number>;
      };
      metadata: {
        timestamp: number;
        commitment?: string;
      };
    }
    
    class DelegateAccountAnalyzer {
      async analyzeDelegateAccounts(
        delegate: PublicKey,
        config: { programId: PublicKey; commitment?: string }
      ): Promise<DelegateAccountAnalysis> {
        const accounts = await connection.getTokenAccountsByDelegate(delegate, config);
        
        const byMint: Record<string, bigint> = {};
        const byOwner: Record<string, number> = {};
        let totalBalance = BigInt(0);
        
        accounts.value.forEach(account => {
          const mint = account.account.data.parsed.info.mint;
          const owner = account.account.data.parsed.info.owner;
          const amount = BigInt(account.account.data.parsed.info.tokenAmount.amount);
          
          byMint[mint] = (byMint[mint] || BigInt(0)) + amount;
          byOwner[owner] = (byOwner[owner] || 0) + 1;
          totalBalance += amount;
        });
        
        return {
          delegate: delegate.toBase58(),
          accounts: accounts.value.map(account => ({
            pubkey: account.pubkey,
            mint: account.account.data.parsed.info.mint,
            balance: account.account.data.parsed.info.tokenAmount.amount,
            owner: account.account.data.parsed.info.owner
          })),
          metrics: {
            totalAccounts: accounts.value.length,
            totalBalance: totalBalance.toString(),
            byMint: Object.fromEntries(
              Object.entries(byMint).map(([mint, amount]) => [mint, amount.toString()])
            ),
            byOwner
          },
          metadata: {
            timestamp: Date.now(),
            commitment: config.commitment
          }
        };
      }
    }
    
  2. Delegate Account Monitoring

    interface DelegateAccountChange {
      delegate: string;
      changes: Array<{
        type: 'added' | 'removed' | 'modified';
        account: string;
        previousBalance?: string;
        currentBalance?: string;
      }>;
      metadata: {
        timestamp: number;
      };
    }
    
    class DelegateAccountMonitor {
      private previousAccounts: Map<string, string> = new Map();
      
      async monitorDelegateAccounts(
        delegate: PublicKey,
        config: { programId: PublicKey; commitment?: string }
      ): Promise<DelegateAccountChange | null> {
        const accounts = await connection.getTokenAccountsByDelegate(delegate, config);
        const currentAccounts = new Map(
          accounts.value.map(account => [
            account.pubkey,
            account.account.data.parsed.info.tokenAmount.amount
          ])
        );
        
        const changes: Array<{
          type: 'added' | 'removed' | 'modified';
          account: string;
          previousBalance?: string;
          currentBalance?: string;
        }> = [];
        
        // Check for removed or modified accounts
        this.previousAccounts.forEach((balance, account) => {
          if (!currentAccounts.has(account)) {
            changes.push({
              type: 'removed',
              account,
              previousBalance: balance
            });
          } else if (currentAccounts.get(account) !== balance) {
            changes.push({
              type: 'modified',
              account,
              previousBalance: balance,
              currentBalance: currentAccounts.get(account)
            });
          }
        });
        
        // Check for added accounts
        currentAccounts.forEach((balance, account) => {
          if (!this.previousAccounts.has(account)) {
            changes.push({
              type: 'added',
              account,
              currentBalance: balance
            });
          }
        });
        
        this.previousAccounts = currentAccounts;
        
        if (changes.length > 0) {
          return {
            delegate: delegate.toBase58(),
            changes,
            metadata: {
              timestamp: Date.now()
            }
          };
        }
        
        return null;
      }
    }
    
  3. Delegate Account Planning

    interface DelegateAccountPlan {
      delegate: string;
      currentAccounts: Array<{
        pubkey: string;
        mint: string;
        balance: string;
      }>;
      recommendations: Array<{
        type: 'consolidate' | 'diversify' | 'rebalance';
        accounts: string[];
        reason: string;
      }>;
      metadata: {
        timestamp: number;
      };
    }
    
    class DelegateAccountPlanner {
      private readonly minBalancePerAccount = BigInt(1000000); // 1 token
      private readonly maxAccountsPerMint = 5;
      
      async planDelegateAccounts(
        delegate: PublicKey,
        config: { programId: PublicKey; commitment?: string }
      ): Promise<DelegateAccountPlan> {
        const accounts = await connection.getTokenAccountsByDelegate(delegate, config);
        
        const byMint = accounts.value.reduce((acc, account) => {
          const mint = account.account.data.parsed.info.mint;
          if (!acc[mint]) {
            acc[mint] = [];
          }
          acc[mint].push(account);
          return acc;
        }, {} as Record<string, typeof accounts.value>);
        
        const recommendations: Array<{
          type: 'consolidate' | 'diversify' | 'rebalance';
          accounts: string[];
          reason: string;
        }> = [];
        
        Object.entries(byMint).forEach(([mint, mintAccounts]) => {
          // Check for accounts with low balances
          const lowBalanceAccounts = mintAccounts.filter(account => 
            BigInt(account.account.data.parsed.info.tokenAmount.amount) < this.minBalancePerAccount
          );
          
          if (lowBalanceAccounts.length > 0) {
            recommendations.push({
              type: 'consolidate',
              accounts: lowBalanceAccounts.map(account => account.pubkey),
              reason: `Accounts with balances below minimum threshold for mint ${mint}`
            });
          }
          
          // Check for too many accounts per mint
          if (mintAccounts.length > this.maxAccountsPerMint) {
            recommendations.push({
              type: 'consolidate',
              accounts: mintAccounts.map(account => account.pubkey),
              reason: `Too many accounts (${mintAccounts.length}) for mint ${mint}`
            });
          }
        });
        
        return {
          delegate: delegate.toBase58(),
          currentAccounts: accounts.value.map(account => ({
            pubkey: account.pubkey,
            mint: account.account.data.parsed.info.mint,
            balance: account.account.data.parsed.info.tokenAmount.amount
          })),
          recommendations,
          metadata: {
            timestamp: Date.now()
          }
        };
      }
    }