Summary
Solana exposes a JSON-RPC interface with a broad set of methods for reading accounts, submitting transactions, and subscribing to live updates. The methods you enable depend on your workload: wallets need blockhash and sendTransaction, indexers need getProgramAccounts and getSignaturesForAddress, and trading systems lean on WebSocket subscriptions and priority fee estimation. This reference maps common Solana RPC methods to real use cases, shows request examples, and explains the limits that shape production architecture. It also covers how to pick an endpoint, when shared public RPC is enough, and when a dedicated Solana node from OnFinality makes more sense for sustained or high-volume traffic.
Solana's JSON-RPC API is the primary way applications read state and submit transactions. Unlike EVM chains, where a small set of methods covers most use cases, Solana exposes a wider surface: account queries, program-derived lookups, blockhash retrieval, transaction simulation, and WebSocket subscriptions. The method you call, and how often you call it, determines whether a shared endpoint is sufficient or whether you need dedicated infrastructure.
Start here: match your workload to a method set
Before optimizing anything, identify which category your application falls into. The table below maps common Solana workloads to the methods they depend on and the endpoint characteristics that matter most.
| Workload | Core methods | Endpoint characteristics to prioritize |
|---|---|---|
| Wallet or dapp frontend | getLatestBlockhash, getBalance, sendTransaction, getSignatureStatuses | Low-latency HTTP, reliable transaction forwarding |
| Indexer or analytics | getProgramAccounts, getSignaturesForAddress, getTransaction | High request throughput, archive depth, stable pagination |
| Trading or bot | onAccountChange, onLogs, getRecentPrioritizationFees, sendTransaction | WebSocket stability, low latency, burst capacity |
| NFT or token tooling | getTokenAccountsByOwner, getAccountInfo, getProgramAccounts | Consistent response times, filtering support |
If your workload is mostly read-heavy with occasional writes, a shared RPC endpoint such as OnFinality's Solana public endpoint can cover early development. If you run sustained subscriptions, large getProgramAccounts scans, or high transaction volume, a dedicated node removes noisy-neighbor effects and gives you predictable capacity. You can review RPC pricing and supported RPC networks to compare options.
Reading accounts and balances
The most common Solana RPC methods retrieve account state. These are HTTP POST calls with a JSON body.
curl https://solana.api.onfinality.io/public \
-X POST -H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getBalance",
"params": ["<PUBKEY>"]
}'
Key methods in this group:
- getBalance returns the lamport balance for a public key.
- getAccountInfo returns the account's data, owner, lamports, and executable flag.
- getTokenAccountsByOwner lists SPL token accounts for a wallet, with optional mint filtering.
- getProgramAccounts returns all accounts owned by a program. This is powerful but expensive; always use filters (dataSize, memcmp) to narrow results.
getProgramAccounts is the method most likely to hit provider limits. Without filters, it can scan millions of accounts. If you rely on it heavily, confirm that your provider supports it at your required scale and consider a dedicated node where you control the configuration.
Submitting and tracking transactions
Writing to Solana involves a specific sequence: fetch a recent blockhash, build and sign the transaction, send it, then confirm it.
// Minimal send flow using fetch against a Solana RPC endpoint
const endpoint = "https://solana.api.onfinality.io/public";
async function rpc(method, params) {
const res = await fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
});
return res.json();
}
const { result } = await rpc("getLatestBlockhash", [{ commitment: "confirmed" }]);
// build and sign transaction using result.value.blockhash
// then:
// await rpc("sendTransaction", [signedTxBase64, { encoding: "base64" }]);
Methods to know:
- getLatestBlockhash returns a blockhash and its validity window. Blockhashes expire, so fetch fresh ones close to send time.
- sendTransaction submits a signed transaction. Set
skipPreflightcarefully; preflight catches many errors but adds latency. - simulateTransaction runs a transaction without committing it, useful for estimating compute units and catching failures.
- getSignatureStatuses and getTransaction let you confirm whether a transaction landed.
- getRecentPrioritizationFees helps you set a competitive priority fee during congestion.
A common pitfall is caching a blockhash too long. If the blockhash expires before the transaction lands, the network rejects it. Fetch a new blockhash for each attempt and retry with backoff.
WebSocket subscriptions and their limits
Solana supports WebSocket subscriptions for real-time updates. OnFinality's Solana endpoint exposes a WebSocket transport at wss://solana.api.onfinality.io/public-ws.
Common subscription methods:
- accountSubscribe watches a single account for changes.
- logsSubscribe streams logs for a program or account.
- signatureSubscribe notifies when a specific transaction confirms.
- slotSubscribe and rootSubscribe track slot progression.
const ws = new WebSocket("wss://solana.api.onfinality.io/public-ws");
ws.onopen = () => {
ws.send(JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "logsSubscribe",
params: [{ mentions: ["<PROGRAM_ID>"] }, { commitment: "confirmed" }],
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
// handle log notification
};
WebSocket connections are stateful and can drop. Production clients should implement reconnect logic, resubscribe on reconnect, and treat the stream as eventually consistent. If you maintain many concurrent subscriptions, connection limits and server-side idle timeouts become relevant; this is where dedicated nodes help, because you are not sharing subscription capacity with other tenants.
Production readiness checklist
Use this checklist before moving a Solana integration to production.
| Check | Why it matters |
|---|---|
| Blockhash freshness | Expired blockhashes cause failed sends |
| Commitment level | processed is fast but can be rolled back; confirmed and finalized trade speed for safety |
| Retry strategy | Network congestion and dropped transactions require idempotent retries |
| getProgramAccounts filters | Unfiltered scans are slow and may be rate-limited |
| WebSocket reconnect | Dropped subscriptions silently stop updates |
| Failover endpoint | A single endpoint is a single point of failure |
| Priority fee logic | Static fees underperform during congestion |
If several of these are hard to manage on a shared endpoint, that is the signal to evaluate a dedicated Solana node. OnFinality provides RPC API access and dedicated node infrastructure across supported networks, including Solana, so you can scale capacity without operating validators yourself.
Commitment levels and why they change results
Every read method accepts a commitment parameter. The three you will use most:
- processed reflects the most recent slot but may be rolled back.
- confirmed is voted on by a supermajority and is the usual choice for user-facing balances.
- finalized is irreversible and best for settlement logic.
Mixing commitment levels across calls causes confusing bugs, such as a balance that appears then disappears. Pick a level per feature and apply it consistently. For transaction confirmation, confirmed is a reasonable default; for financial settlement, use finalized.
Debugging common Solana RPC failures
| Symptom | Likely cause | Next step |
|---|---|---|
| Transaction not confirmed | Expired blockhash or low priority fee | Refetch blockhash, raise priority fee, resend |
getProgramAccounts times out | Missing filters or oversized result | Add dataSize/memcmp filters, paginate |
| WebSocket stops updating | Connection dropped | Reconnect and resubscribe |
| Inconsistent balances | Mixed commitment levels | Standardize commitment per feature |
| 429 responses | Request rate exceeded | Batch requests, cache reads, or move to dedicated capacity |
When you see 429s or latency spikes, capture the method name and payload size. Large getProgramAccounts calls and unfiltered log subscriptions are the usual culprits. Reducing payload size often resolves the issue without changing providers.
Choosing between shared and dedicated Solana RPC
Shared endpoints are cost-effective for development, low-traffic dapps, and read-heavy dashboards. Dedicated nodes make sense when you need consistent throughput, heavy subscription counts, large account scans, or isolation from other tenants' traffic. OnFinality offers both models, so you can start on a shared endpoint and move to a dedicated node as usage grows. Review RPC pricing for current options and how to choose an RPC provider for evaluation criteria.
Key Takeaways
- Solana RPC methods split into reads (getAccountInfo, getBalance, getProgramAccounts), writes (sendTransaction), and subscriptions (logsSubscribe, accountSubscribe).
- Always fetch a fresh blockhash before sending; expired blockhashes are a leading cause of failed transactions.
- Use commitment levels consistently; mixing them creates hard-to-debug inconsistencies.
- Filter getProgramAccounts aggressively to avoid timeouts and rate limits.
- WebSocket clients must handle reconnects and resubscription.
- Shared endpoints suit low-traffic apps; dedicated nodes suit sustained, high-volume, or subscription-heavy workloads.
Frequently Asked Questions
What is the most-used Solana RPC method? For wallets and dapps, getLatestBlockhash, getBalance, and sendTransaction are the most common. Indexers rely more on getProgramAccounts and getSignaturesForAddress.
Does OnFinality support Solana WebSocket subscriptions? Yes. The Solana endpoint exposes both HTTP and WebSocket transports. See the Solana network page for details.
Why does getProgramAccounts fail or time out? Usually because the query lacks filters and returns too much data. Add dataSize or memcmp filters and paginate results.
Should I use a public or dedicated Solana RPC endpoint? Start public for development and low traffic. Move to a dedicated node when you need predictable throughput, many subscriptions, or isolation from shared traffic.
How do I set priority fees? Call getRecentPrioritizationFees, then set a fee that reflects current congestion. Static fees often underperform during busy periods.