Typed clients are how off-chain TypeScript talks to a Solana program without hand-encoding discriminators, account metas, and Borsh layouts. Once you treat the IDL as the shared contract and every client generator as a consumer of that contract, Anchor's Program API, Codama output, gill helpers, instruction builders, and account decoders stop looking like competing libraries and start looking like one pipeline from anchor build to a signed transaction.
A program's public surface is described by an IDL; typed clients regenerate instruction builders, codecs, and fetch helpers from that JSON so TypeScript cannot silently invent layouts that diverge from on-chain encoding.
Insight: Hand-written account lists and arg buffers drift; one IDL-driven client surface cuts mainnet encode bugs, speeds UI and bot work, and makes CI able to fail when the interface moves without a client update.
Key Concepts:Anchor IDL, Anchor TS Program, Codama + @solana/kit, gill, typed instruction builders, fetch/decode helpers, discriminators and Borsh, CI regen and drift checks.
When to Use: Shipping or maintaining TypeScript apps against Anchor (or IDL-described) programs, choosing between classic Anchor client and kit-first stacks, or designing monorepo release gates for program plus frontend.
Limitations/Trade-offs: Client quality tracks IDL quality; remaining accounts and some native programs need extra docs; Anchor TS and Codama target different runtimes so pick one transaction story per app; gill does not generate your program's IDL surface.
Related Topics: Anchor TS client, Codama, gill, building instructions, fetching and decoding accounts, keeping clients in sync.
Solana programs expose bytes: instruction data (usually an 8-byte discriminator plus args) and account lists with signer and writable flags. Nothing on the wire is "TypeScript-native." Without a shared description of those shapes, every dApp, script, and indexer invents its own encoding and eventually disagrees with the program.
Anchor fills that gap for framework programs. Macros on instructions, accounts, events, and errors feed anchor build, which emits IDL JSON under target/idl/. That file is the contract for off-chain work in this section: instruction names and accounts, types, errors, events, and program address metadata. Typed clients exist to consume that contract, not to replace it.
Think of the off-chain stack as layers from IDL out to UX:
Anchor TS client (@coral-xyz/anchor): load IDL into new Program(...), call program.methods.<ix>(...).accounts(...).rpc(). Strong fit for anchor test, brownfield dApps, and teams already on Anchor Provider patterns.
Codama: parse Anchor IDL into a node graph and render @solana/kit-oriented modules (get*Instruction, fetch* / decode* helpers, error maps). Strong fit for greenfield kit stacks and tree-shakable transaction assembly.
@solana/kit 7.0.0 is the modern RPC, codec, signer, and transaction-message layer. Codama is the usual bridge from Anchor IDL into kit types. Kit alone does not know your program's account layouts; without Codama (or hand-written codecs) you are back to inventing bytes.
gill sits above kit as optional convenience: client factory patterns, moniker-based RPC, and common send helpers. It does not replace Codama output for your custom program. You still generate program-specific builders and decoders from the IDL, then compose them with kit or gill send paths.
Reads and writes share the same generated surface: builders encode discriminator + args and account metas; fetch helpers decode RPC bytes with the matching layout. One generator keeps both paths aligned.
Platform pins for this site: Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, and @solana/kit 7.0.0.
programs/.../lib.rs --macros--> anchor build | v target/idl/foo.json | +--------------------------+--------------------------+ v v Anchor TS Program(idl) Codama CLI + renderers methods / account.fetch get*Instruction, fetch* | | v v classic Provider / tests kit transaction messages
Regenerate on every public interface change. Hand-editing generated folders or the IDL JSON to "match the UI" creates silent drift: the program still encodes the macro-defined layout while clients encode fiction. Details for generation live in Codama; the classic path is The Anchor TS Client.
Do not mix kit transaction assembly with web3.js instruction objects without a deliberate bridge. Pick one client runtime per app and regenerate when the IDL changes. Prefer Codama + kit for new modules; keep Anchor TS where migration cost dominates.
A generated instruction builder answers: which accounts, which flags, which arg types, which discriminator. You pass addresses and signers; the builder emits a kit-native (or Anchor-native) instruction object ready to append into a transaction message.
Never hand-reorder account metas. Order and flags come from the IDL; init-style flows still need System Program and funding accounts when required. Deep dive: Building Instructions.
RPC returns owner, lamports, and data bytes (getAccountInfo or a generated fetch helper).
Generated decoder checks discriminator / layout and returns a typed object.
Callers handle null (missing or closed accounts) before UI or business logic.
RPC getAccountInfo(address) | v raw bytes + owner | v decodeFoo / fetchFoo --> { data: { ... }, ... } | null
Wrong owner, cluster program id, or a stale decoder yields garbage that looks valid until a write fails. Prefer generated fetch* helpers; use raw RPC + decode* for custom batching. Details: Fetching & Decoding Accounts.
gill reduces kit boilerplate (client creation, monikers, send-and-confirm patterns). Program-specific knowledge still comes from Codama (or Anchor TS). A healthy composition is:
Multi-program apps: never merge IDL surfaces into one JSON. Namespace generated output (clients/program_a, clients/program_b) and avoid export name collisions.
Indexers and bots are clients too; a stale worker decoder is the same bug class as a stale UI hook, only quieter.
Native programs may lack a complete Anchor IDL. Prefer a maintained compatible IDL, Codama from a custom description, or hand-built kit codecs.
Remaining accounts often sit outside fixed IDL lists. Document them and pass them explicitly; codegen may not invent the full runtime account graph.
For design reviews: which TS runtime you standardize on, who owns the IDL artifact, how CI detects drift, whether gill is allowed, and how breaking IDL changes roll out.
"Typed clients mean I can skip learning kit messages." Builders still land in transaction messages; simulation, fees, and signers remain your responsibility.
"Anchor TS and Codama are drop-in replacements." Both read IDL, but they target different client stacks; choose one primary transaction path per app.
"gill generates my program client." gill helps with kit workflows; program-specific instructions and decoders still come from Codama or Anchor TS.
"I can hand-edit generated files for a hotfix." The next regen wipes them; put overrides in wrapper modules only.
"If the UI type-checks, the IDL matches mainnet." Types match the IDL you generated against, not necessarily the deployed program; pin program id, cluster, and IDL hash.
"Fetch helpers are optional polish." Shared decoders prevent two layouts (read path vs write path) from diverging inside one codebase.
"CI regen is overkill for a solo repo." Drift appears the first time you change an account field and forget a second package.
"Importing the full IDL JSON at runtime is always fine." Large IDLs bloat bundles; prefer tree-shakable generated modules or lazy loads.
What is the single most important idea in typed clients?
One versioned IDL is the shared contract; every typed TypeScript helper is a regenerated consumer of that contract, not a parallel hand-written ABI.
Where does the IDL come from?
For Anchor programs, anchor build (0.32.1 on this site) emits JSON under target/idl/ from macros. Commit and review that artifact as API product.
When should I use the Anchor TS client?
When you maintain classic Anchor tests or brownfield dApps on the Provider / .methods model and are not yet standardizing on kit transaction assembly.
When should I use Codama?
When the app standardizes on @solana/kit 7.0.0 and you want generated instruction builders and account decoders that match the Anchor IDL without hand codecs.
How does Codama relate to the Anchor IDL?
Codama ingests Anchor IDL JSON (via nodes-from-anchor and related packages), builds an internal graph, and renders kit-oriented TypeScript. Rebuild when the IDL changes and pin the CLI/renderer versions in CI.
Is gill required?
No. It is optional sugar for kit RPC and send patterns. Program-specific typing still depends on Codama or Anchor TS.
How do I build a typed instruction?
Call the generated get*Instruction (Codama) or program.methods.* (Anchor TS) with accounts and args, then place the result in your chosen send path. See Building Instructions.
How do I fetch a typed account?
Use generated fetch* helpers with kit RPC, or getAccountInfo plus decode*. Always handle missing accounts and verify owner/program id assumptions. See Fetching & Decoding Accounts.
What breaks if IDL and program diverge?
Wrong discriminators, account order, or layouts cause simulation failures, cryptic custom errors, corrupt account decodes, or silent UI lies that fail only on write.
How should CI keep clients in sync?
Build the program, regenerate clients, git diff --exit-code on generated paths, and run tests. Pair with release tags that include program hash and IDL version. See Keeping Clients in Sync.
Can I mix kit and web3.js in one feature?
Only with an explicit bridge. Prefer one runtime per feature boundary so instruction and address types do not thrash.
Do typed clients replace on-chain validation?
No. Clients reduce encode mistakes; the program still enforces constraints, ownership, and signer rules. Simulation is still mandatory for serious flows.
How do multi-program monorepos stay clean?
One IDL and one generated output directory per program, shared CI regen for all, and explicit package exports so import paths cannot silently cross wires.
Where does @solana/kit fit relative to Codama?
Kit is the RPC and transaction stack (this site: 7.0.0). Codama bridges Anchor IDL into that stack. Kit does not compile sBPF or own the IDL format.