Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: solana-rpc description: Direct Solana blockchain interaction via JSON-RPC — account lookups, token balances, transaction submission, and program queries
Solana RPC — Direct Blockchain Interaction
The Solana JSON-RPC API provides direct read/write access to the blockchain. Use it for account state queries, token balance lookups, transaction building and submission, and program account enumeration. This is the low-level foundation when higher-level APIs (Birdeye, Helius, SolanaTracker) don't have the data you need.
Quick Start
import httpxRPC = os.getenv("SOLANA_RPC_URL", "https://api.mainnet-beta.solana.com")def rpc_call(method: str, params: list = None) -> dict:resp = httpx.post(RPC, json={"jsonrpc": "2.0", "id": 1,"method": method, "params": params or [],}, timeout=30.0)return resp.json()# Get SOL balanceresult = rpc_call("getBalance", ["WALLET_PUBKEY"])sol_balance = result["result"]["value"] / 1e9# Get latest blockhashresult = rpc_call("getLatestBlockhash")blockhash = result["result"]["value"]["blockhash"]
RPC Providers
| Provider | Free Tier | Paid | Notes | |
|---|---|---|---|---|
| Helius | 50K credits/day | $49+/mo | Enhanced RPCs, DAS API | |
| QuickNode | Limited | $49+/mo | Multi-chain, WebSocket | |
| Triton | No free tier | ~$300+/mo | Yellowstone gRPC bundled | |
| Shyft | Limited | $49+/mo | Yellowstone gRPC bundled | |
| Alchemy | 300M CU/mo | Scaling | Good free tier | |
| Public (mainnet-beta) | Free | — | Rate limited, unreliable |
Recommendation: Use Helius or QuickNode for development. Never use public RPC for production trading.
Core Read Methods
Account & Balance
# SOL balance (in lamports, divide by 1e9 for SOL)getBalance(pubkey, {commitment: "confirmed"})# Full account info (data, owner, lamports, executable)getAccountInfo(pubkey, {encoding: "jsonParsed"})# Multiple accounts in one callgetMultipleAccounts([pubkey1, pubkey2], {encoding: "jsonParsed"})
Token Accounts
# All SPL token accounts owned by a walletgetTokenAccountsByOwner(wallet_pubkey, {"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"}, {"encoding": "jsonParsed"})# Token balance for a specific token accountgetTokenAccountBalance(token_account_pubkey)# Largest token accounts (top holders)getTokenLargestAccounts(mint_pubkey)# Total supply of a tokengetTokenSupply(mint_pubkey)
Transaction Data
# Get parsed transaction by signaturegetTransaction(signature, {"encoding": "jsonParsed","maxSupportedTransactionVersion": 0,})# Recent transaction signatures for an addressgetSignaturesForAddress(pubkey, {"limit": 20,"before": "optional_signature", # pagination cursor})# Transaction statusgetSignatureStatuses([sig1, sig2])
Block & Slot
# Current slotgetSlot({commitment: "confirmed"})# Block datagetBlock(slot, {"encoding": "jsonParsed","transactionDetails": "full","maxSupportedTransactionVersion": 0,})# Latest blockhash (needed for tx building)getLatestBlockhash({commitment: "confirmed"})# Slot leader schedulegetLeaderSchedule()
Program Accounts
# All accounts owned by a program (with filters)getProgramAccounts(program_pubkey, {"encoding": "jsonParsed","filters": [{"dataSize": 165}, # Filter by account data size{"memcmp": { # Filter by data content"offset": 32,"bytes": "base58_encoded_value",}},],})
Warning: getProgramAccounts without filters can return millions of results and timeout. Always use dataSize and/or memcmp filters.
Priority Fees
# Recent priority fee estimatesgetRecentPrioritizationFees([account_pubkey])# Returns array of { slot, prioritizationFee } for recent slots# Minimum rent for accountgetMinimumBalanceForRentExemption(data_length)
Write Methods
Send Transaction
# Send a signed, serialized transactionsendTransaction(base64_tx, {"encoding": "base64","skipPreflight": False,"preflightCommitment": "confirmed","maxRetries": 3,})# Simulate before sendingsimulateTransaction(base64_tx, {"encoding": "base64","sigVerify": False,"commitment": "confirmed",})
Transaction Confirmation
import timedef confirm_transaction(rpc_url: str, signature: str, timeout: float = 30.0) -> bool:"""Poll for transaction confirmation."""start = time.time()while time.time() - start < timeout:result = rpc_call("getSignatureStatuses", [[signature]])statuses = result.get("result", {}).get("value", [None])if statuses[0] is not None:status = statuses[0]if status.get("err"):return Falseif status.get("confirmationStatus") in ("confirmed", "finalized"):return Truetime.sleep(0.5)return False
Commitment Levels
| Level | Description | Use When | |
|---|---|---|---|
processed | Single node confirmation | Speed over safety | |
confirmed | Supermajority (2/3+) | Default for trading | |
finalized | Maximum supermajority + 31 slots | Critical operations |
Always specify commitment explicitly. Default varies by provider.
Common Patterns
Get All Token Holdings for a Wallet
def get_wallet_tokens(wallet: str) -> list[dict]:"""Get all SPL token holdings with metadata."""result = rpc_call("getTokenAccountsByOwner", [wallet,{"programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"},{"encoding": "jsonParsed"},])tokens = []for acct in result["result"]["value"]:info = acct["account"]["data"]["parsed"]["info"]tokens.append({"mint": info["mint"],"amount": int(info["tokenAmount"]["amount"]),"decimals": info["tokenAmount"]["decimals"],"ui_amount": info["tokenAmount"]["uiAmount"],})return [t for t in tokens if t["amount"] > 0]
Get Top Holders of a Token
def get_top_holders(mint: str) -> list[dict]:"""Get the 20 largest holders of a token."""result = rpc_call("getTokenLargestAccounts", [mint])supply_result = rpc_call("getTokenSupply", [mint])total_supply = int(supply_result["result"]["value"]["amount"])holders = []for acct in result["result"]["value"]:amount = int(acct["amount"])holders.append({"address": acct["address"],"amount": amount,"decimals": acct["decimals"],"ui_amount": acct["uiAmount"],"percentage": amount / total_supply * 100 if total_supply > 0 else 0,})return holders
Batch RPC Calls
def rpc_batch(calls: list[tuple[str, list]]) -> list[dict]:"""Execute multiple RPC calls in a single HTTP request."""payload = [{"jsonrpc": "2.0", "id": i, "method": method, "params": params}for i, (method, params) in enumerate(calls)]resp = httpx.post(RPC, json=payload, timeout=30.0)results = resp.json()results.sort(key=lambda r: r["id"])return [r.get("result") for r in results]
Key Program IDs
| Program | ID | |
|---|---|---|
| System | 11111111111111111111111111111111 | |
| SPL Token | TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA | |
| Token-2022 | TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb | |
| Associated Token | ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL | |
| Raydium AMM | 675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8 | |
| Raydium CLMM | CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK | |
| Orca Whirlpool | whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc | |
| Meteora DLMM | LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo | |
| PumpFun | 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P | |
| Jupiter v6 | JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 | |
| Compute Budget | ComputeBudget111111111111111111111111111111 |
When to Use Direct RPC vs Higher-Level APIs
| Need | Use | |
|---|---|---|
| Token balance check | Direct RPC (getTokenAccountsByOwner) | |
| Top 20 holders | Direct RPC (getTokenLargestAccounts) | |
| Historical OHLCV | Birdeye or SolanaTracker | |
| Parsed transaction history | Helius Enhanced Transactions | |
| Token metadata (name, image) | Helius DAS API | |
| Real-time streaming | Yellowstone gRPC | |
| Wallet PnL tracking | SolanaTracker | |
| Token risk scoring | SolanaTracker | |
| Cross-chain data | DexScreener or CoinGecko |
Files
References
references/methods.md— Complete RPC method reference with parameters and response schemasreferences/error_handling.md— Error codes, rate limits, timeout handling, retry strategiesreferences/providers.md— RPC provider comparison with pricing and features
Scripts
scripts/wallet_scanner.py— Scan wallet for all token holdings with balancesscripts/token_holders.py— Get top holders and concentration metrics for any token