Intermediate · LESSON 01 OF 06
1. Build a reliable read-only client
By the end, you can design a client that distinguishes missing, stale, and failed data.
Read the workflow
The learner chooses a cluster and public address; the client calls getBalance without connecting a signing wallet or sending a transaction. The response carries lamports and a context slot, which the client checks against the request and any minimum context slot. A request generation prevents an older response from replacing the active view. A timeout remains unavailable rather than becoming zero, while HTTP 429 follows Retry-After guidance with bounded backoff. The interface preserves the cluster, address, commitment, slot, and time for each observation.
- NETWORK + WALLET
- READ-ONLY RPC
- VALIDATE SLOT
- DISPLAY OR RETRY
FIELD NOTE 01
Separate the interface from the evidence
An RPC client requests network data from a service. Treat the service as a dependency with timeouts, rate limits, and possible stale responses. Render loading, empty, error, and successful states separately. A failed request must not become a balance of zero.
FIELD NOTE 02
Bind requests to their context
Attach the cluster, account, commitment, and request generation to every read. If a learner switches wallets while an old request is pending, discard the old response instead of displaying it for the new wallet. Record the slot when available so observations can be compared meaningfully.
FIELD NOTE 03
A bounded client exercise
Design a balance viewer with an explicit network selector, address validation, timeout, and manual retry. Return integer lamports from the data layer and format only at the display boundary. Inject a fake transport in tests to simulate a slow response, a rate-limit response, and a wallet change.
FIELD NOTE 04
Make every response carry its observation context
An RPC result is an observation made by one endpoint at one time, not a timeless fact. Preserve the response context slot alongside account data, and show the selected cluster and commitment in the interface. Validate addresses before sending requests; apply a timeout; and distinguish malformed input, not-found, rate-limited, provider failure, and a valid zero balance. Keep raw lamports as integers until formatting, and never silently convert a failed request into zero. If the user changes wallet or cluster while a request is pending, tag each request with that context and discard late responses from the old selection. These small choices prevent a plausible but incorrect balance from being presented as current evidence.
FIELD NOTE 05
Carry context with every response
A balance response is meaningful only alongside the cluster, public address, commitment, slot, and time at which it was read. Keep the exact lamport value as an integer and keep the slot with it. If the learner switches from one address to another while a request is pending, tag each request with a generation number and discard any response from an older generation. Otherwise a correct response can appear beside the wrong wallet. If a second provider gives a different balance, compare its slot and commitment before deciding that the ledger disagrees.
FIELD NOTE 06
Design errors as real result states
A client should distinguish an invalid address, timeout, rate limit, malformed response, absent account, and valid zero value. These states have different recovery steps. A timeout can be retried with backoff; an invalid address needs correction; a provider error should stay visible. Public Solana RPC endpoints may return HTTP 429 when rate-limited; respect the `Retry-After` header and use bounded backoff. If you keep the last good value on screen, label it stale and show its original slot and timestamp. Never replace a failed response with zero, and never let a loading spinner hide the fact that an earlier observation may no longer match the selected address.
FIELD NOTE 07
Test behavior without trusting the network
Inject the transport or RPC object so tests can choose exact responses and delays. Check that a successful read preserves the returned slot, that integer formatting is exact, and that an invalid address never invokes the transport. Then delay a response, switch the selected address, and prove that the older result is ignored. Add cases for rate limiting, provider rejection, and malformed JSON values. These tests establish client behavior under controlled inputs; they do not prove a public RPC endpoint is honest, available, or current. Keep those evidence claims separate in the capstone report.
FIELD NOTE 08
Choose a current SDK and document its limits
Solana’s current TypeScript documentation recommends `@solana/kit` for new development and labels `@solana/web3.js` the legacy SDK. Kit composes RPC, signer, and transaction capabilities as plugins. Existing ecosystem libraries may still depend on web3.js, so choose a compatible set deliberately and test the exact APIs you use instead of assuming the two SDKs are interchangeable. The Builder workbook pins Kit 8.3.0 and uses a fake RPC in automated tests; its optional Devnet command reads a public balance only. Version support is directional: `@solana/web3.js` 1.99.0 and later can read and deserialize v1 transactions when the RPC request sets `maxSupportedTransactionVersion: 1`, but web3.js v1 cannot build, sign, or send v1; earlier v1 releases are limited to legacy and v0. Use a current, pinned `@solana/kit` 8.x stack for v1 construction and sending, and verify the wallet path you will ship. Pin dependencies, record the SDK and cluster with each observation, and recheck the migration guide when dependencies change. A current SDK does not prove an RPC response is complete or truthful.
MAKE THE CONNECTION
A detail worth keeping
Avoid request races by associating the wallet and network with each pending call. A UI can issue request 1 for Alice and request 2 for Ben; if response 1 arrives last, the display must reject it. Cancellation helps but a generation counter is a useful final guard.
Work through an example
A retry should be bounded and visible. Exponential delay with jitter reduces synchronized load, but after a rate limit the UI must honour provider guidance. Cached readings should include their time and network so a learner knows they may be stale.
Write pseudocode for the viewer and tests for a delayed old-wallet response. Show an error message that keeps the last successful observation visibly labeled as stale.
GUIDED PRACTICE · INTERMEDIATE
Do the work, one step at a time
Use fictional addresses and disposable test data. Do not enter a recovery phrase or private key. Unless a lesson explicitly says “read-only Devnet,” use paper or a local test and do not connect to a public network.
- Download and unzip Builder workbook 01; keep the folder outside your course repository.
- Run npm ci with Node.js 20 or later to install the pinned Solana Kit dependency.
- Run npm test and explain why every test uses a fake RPC instead of a wallet or network.
- Choose a public address and run npm run read -- <PUBLIC_SOLANA_ADDRESS> against the fixed Devnet endpoint.
- Record the cluster, confirmed commitment, context slot, raw lamports, and exact SOL display.
Before you move on, check your reasoning
- Build a read-only account lookup using the current official Kit client guide.
- Mock a slow result for wallet A followed by a fast result for wallet B.
- Assert that only B is shown and an RPC failure is not rendered as zero.
OPEN SELF-CHECK · UNGRADED
Pause and test your reasoning
A wallet changes from address A to B. A slow balance request for A finishes after the request for B. Which UI behavior is safest?
- Display whichever response arrived last, even if it belongs to A.
- Associate each request with its address or generation and ignore a stale result that no longer matches the active context.
- Show zero for B until the older request finishes.
Reveal one best answer and its explanation
One best answer: Associate each request with its address or generation and ignore a stale result that no longer matches the active context.
Network responses can arrive out of order. Bind each result to the request context and active generation before rendering it; otherwise a valid old balance can be mislabeled as the newly selected wallet’s state.
Sources: getBalance ↗ · Solana RPC Overview ↗
This practice is not scored, saved, or part of a certificate. Account-based lesson checkpoints and level exams remain separate.
Scored checkpoints and level exams are online and require a free account. They are not included in this pack.
Optional lab files
These files are included with the pack. Follow the safety and toolchain notes in the lesson before running a lab; a Devnet read requires an internet connection.
READ THE SOURCE
Go deeper in the official docs
Reviewed on 2026-09-29. Protocol documentation can change; check the linked page’s current version when you reconnect.