Skip to content

Arete documentation

Program Read

For the complete documentation index optimized for AI agents, see llms.txt or llms-full.txt. A markdown version of this page is available by appending .md to the URL or sending Accept: text/markdown.

For AI agents: the documentation index is at llms.txt (full corpus: llms-full.txt). A markdown source for this page is /using-programs/program-reads.md.

Program Read is how you look up a program’s on-chain accounts and get them back as typed data instead of raw bytes. It is attached to one published program release. The generated SDK already knows the exact program identity, the account schemas, and where the service lives, so you never copy a decoder around or send a schema with each request.

An address on its own doesn’t tell you which version of a schema should decode the bytes stored there. Programs get upgraded, and layouts change. The generated reader is tied to the exact Program Release chosen in arete.lock, which gives your client a reproducible link between:

  • the executable program identity;
  • the normalized schema used to decode it;
  • the generated TypeScript, Rust, or Python type; and
  • the hosted read capability.

Don’t swap a generated reader for some other RPC decoder unless you really do mean to step outside the installed contract.

Inspect the descriptor before relying on hosted reads:

Terminal window
a4 explore catalog program <slug> --json

Look for read coverage, Program Read availability, the expected authentication policy, and a verified SDK target. A cataloged program may still be build-only.

Generated account names and arguments come from the installed program:

const program = session.programs.myProgram;
const account = await program.accounts.position.fetch(positionAddress);
const many = await program.accounts.position.fetchMany(positionAddresses);
const exists = await program.accounts.position.exists(positionAddress);

Use the generated types rather than substituting the placeholder names above. Batch results remain aligned with their input addresses, including missing accounts.

The React surface exposes the same generated account readers on its connected program object. Account readers are asynchronous functions rather than React hooks, so call them from your application data layer, an effect, or a query library. Read-only calls do not require a wallet:

import { useEffect, useState } from "react";
const [position, setPosition] = useState<Position | null>();
const arete = useArete(MY_STACK);
useEffect(() => {
let active = true;
void arete.programs.myProgram.accounts.Position.fetch(positionAddress).then(
(value) => {
if (active) setPosition(value);
},
);
return () => {
active = false;
};
}, [arete, positionAddress]);

Inspect the generated declarations for the exact account name and result type. Handle missing data separately from loading and errors.

Generated Rust programs expose typed account clients on the connected client:

let position = a4
.programs
.my_program
.position_accounts()?
.fetch(&position_address)
.await?;
position = await a4.programs.my_program.accounts.position.fetch(position_address)

Python package availability is descriptor-driven. See Python SDK for its current release status.

Use Program Read when you know an account address and need its current decoded state. Use a live view when you need:

  • a collection discovered by application criteria;
  • state assembled from several accounts or instructions;
  • a sorted, filtered, or aggregated window; or
  • continuous updates as matching data changes.

It is common to use both: subscribe to a view to discover or monitor entities, then refresh authoritative program accounts during operation preparation.

Use Program Read for generated program-owned account types. Use session.chain when the data is generic Solana state or when raw bytes are intentionally required.

Generic chain reads →

Hosted Program Read may require the read scope associated with the installed package. Let the generated client resolve its own descriptor and credentials. Do not reuse a live WebSocket URL as a Program Read endpoint.

Treat these outcomes differently:

  • the account does not exist;
  • the account exists but has the wrong owner or discriminator;
  • decoding failed for the pinned schema;
  • authentication or scope is missing; and
  • the hosted read service is unavailable.

Preserve the structured error and request identifier in diagnostics rather than converting every failure into “account not found.”