Parameters

owner
string
required
Public key of the owner (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": "getTokenAccountsByOwner",
  "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 owner
const owner = new PublicKey('4vJ9JU1bJJE96FWSJKvHsmmFADCg4gpZQff4P3bkLZj');
const programId = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
const accounts = await connection.getTokenAccountsByOwner(owner, { programId });
console.log('Token accounts:', accounts);

// Get token accounts by owner with analysis
async function getTokenAccountsByOwnerWithAnalysis(
  owner: PublicKey,
  config: { programId: PublicKey; commitment?: string }
) {
  const accounts = await connection.getTokenAccountsByOwner(owner, 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 owned by the given public key
  2. The owner has full control over 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 owner 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 owned 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 owner public key and configuration
-32007Owner not foundVerify the owner exists
-32008Invalid program IDVerify the program ID is correct

Use Cases

  1. Owner Account Analysis
    interface OwnerAccountAnalysis {
      owner: string;
      accounts: Array<{
        pubkey: string;
        mint: string;
        balance: string;
        delegate?: string;
      }>;
      metrics: {
        totalAccounts: number;
        totalBalance: string;
        byMint: Record<string, string>;
        delegatedAccounts: number;
      };
      metadata: {
        timestamp: number;
        commitment?: string;
      };
    }
    
    class OwnerAccountAnalyzer {
      async analyzeOwnerAccounts(
        owner: PublicKey,
        config: { programId: PublicKey; commitment?: string }
      ): Promise<OwnerAccountAnalysis> {
        const accounts = await connection.getTokenAccountsByOwner(owner, config);
        
        const byMint: Record<string, bigint> = {};
        let totalBalance = BigInt(0);
        let delegatedAccounts = 0;
        
        accounts.value.forEach(account => {
          const mint = account.account.data.parsed.info.mint;
          const amount = BigInt(account.account.data.parsed.info.tokenAmount.amount);
          const delegate = account.account.data.parsed.info.delegate;
          
          byMint[mint] = (byMint[mint] || BigInt(0)) + amount;
          totalBalance += amount;
          if (delegate) {
            delegatedAccounts++;
          }
        });
        
        return {
          owner: owner.toBase58(),
          accounts: accounts.value.map(account => ({
            pubkey: account.pubkey,
            mint: account.account.data.parsed.info.mint,
            balance: account.account.data.parsed.info.tokenAmount.amount,
            delegate: account.account.data.parsed.info.delegate
          })),
          metrics: {
            totalAccounts: accounts.value.length,
            totalBalance: totalBalance.toString(),
            byMint: Object.fromEntries(
              Object.entries(byMint).map(([mint, amount]) => [mint, amount.toString()])
            ),
            delegatedAccounts
          },
          metadata: {
            timestamp: Date.now(),
            commitment: config.commitment
          }
        };
      }
    }
    
  2. Owner Account Monitoring
    interface OwnerAccountChange {
      owner: string;
      changes: Array<{
        type: 'added' | 'removed' | 'modified';
        account: string;
        previousBalance?: string;
        currentBalance?: string;
        previousDelegate?: string;
        currentDelegate?: string;
      }>;
      metadata: {
        timestamp: number;
      };
    }
    
    class OwnerAccountMonitor {
      private previousAccounts: Map<string, {
        balance: string;
        delegate?: string;
      }> = new Map();
      
      async monitorOwnerAccounts(
        owner: PublicKey,
        config: { programId: PublicKey; commitment?: string }
      ): Promise<OwnerAccountChange | null> {
        const accounts = await connection.getTokenAccountsByOwner(owner, config);
        const currentAccounts = new Map(
          accounts.value.map(account => [
            account.pubkey,
            {
              balance: account.account.data.parsed.info.tokenAmount.amount,
              delegate: account.account.data.parsed.info.delegate
            }
          ])
        );
        
        const changes: Array<{
          type: 'added' | 'removed' | 'modified';
          account: string;
          previousBalance?: string;
          currentBalance?: string;
          previousDelegate?: string;
          currentDelegate?: string;
        }> = [];
        
        // Check for removed or modified accounts
        this.previousAccounts.forEach((data, account) => {
          if (!currentAccounts.has(account)) {
            changes.push({
              type: 'removed',
              account,
              previousBalance: data.balance,
              previousDelegate: data.delegate
            });
          } else {
            const current = currentAccounts.get(account)!;
            if (current.balance !== data.balance || current.delegate !== data.delegate) {
              changes.push({
                type: 'modified',
                account,
                previousBalance: data.balance,
                currentBalance: current.balance,
                previousDelegate: data.delegate,
                currentDelegate: current.delegate
              });
            }
          }
        });
        
        // Check for added accounts
        currentAccounts.forEach((data, account) => {
          if (!this.previousAccounts.has(account)) {
            changes.push({
              type: 'added',
              account,
              currentBalance: data.balance,
              currentDelegate: data.delegate
            });
          }
        });
        
        this.previousAccounts = currentAccounts;
        
        if (changes.length > 0) {
          return {
            owner: owner.toBase58(),
            changes,
            metadata: {
              timestamp: Date.now()
            }
          };
        }
        
        return null;
      }
    }
    
  3. Owner Account Planning
    interface OwnerAccountPlan {
      owner: string;
      currentAccounts: Array<{
        pubkey: string;
        mint: string;
        balance: string;
        delegate?: string;
      }>;
      recommendations: Array<{
        type: 'consolidate' | 'diversify' | 'rebalance' | 'delegate';
        accounts: string[];
        reason: string;
      }>;
      metadata: {
        timestamp: number;
      };
    }
    
    class OwnerAccountPlanner {
      private readonly minBalancePerAccount = BigInt(1000000); // 1 token
      private readonly maxAccountsPerMint = 5;
      
      async planOwnerAccounts(
        owner: PublicKey,
        config: { programId: PublicKey; commitment?: string }
      ): Promise<OwnerAccountPlan> {
        const accounts = await connection.getTokenAccountsByOwner(owner, 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' | 'delegate';
          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}`
            });
          }
          
          // Check for accounts without delegates
          const accountsWithoutDelegates = mintAccounts.filter(
            account => !account.account.data.parsed.info.delegate
          );
          
          if (accountsWithoutDelegates.length > 0) {
            recommendations.push({
              type: 'delegate',
              accounts: accountsWithoutDelegates.map(account => account.pubkey),
              reason: `Accounts without delegates for mint ${mint}`
            });
          }
        });
        
        return {
          owner: owner.toBase58(),
          currentAccounts: accounts.value.map(account => ({
            pubkey: account.pubkey,
            mint: account.account.data.parsed.info.mint,
            balance: account.account.data.parsed.info.tokenAmount.amount,
            delegate: account.account.data.parsed.info.delegate
          })),
          recommendations,
          metadata: {
            timestamp: Date.now()
          }
        };
      }
    }