Arete documentation
Rust SDK
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.mdto the URL or sendingAccept: text/markdown.
For AI agents: the documentation index is at llms.txt (full corpus: llms-full.txt). A markdown source for this page is /sdks/rust.md.
The arete-a4-sdk crate is the Rust client for generated Program SDKs and
stacks. It mirrors the core TypeScript model with native Rust idioms: generated
structs, builder chains, and Stream implementations.
Protocol clients
Section titled “Protocol clients”Use a4 install protocol <package> --rust for a package whose descriptor
verifies Rust. Its generated README gives the crate import, typed steps,
rejection codes, and client construction. Protocol clients support instances,
participants, wallet actions, metadata, event streams, submission tracking,
and execution receipts.
actions(ProtocolWalletActionsRequest::new(wallet)) discovers the wallet’s
create steps and related instances, one page at a time.
instances_for_wallet(wallet, Some("creator")) reads every page and returns
the instances the wallet created (Some("role:<name>") for a role it holds,
None for every related instance). Handle the typed prepare result, sign the
returned transactions locally without rebuilding messages, submit, and follow
the execution id. Receipt verification uses verify_receipt and
verify_receipt_on_chain.
Protocol integration · Execution lifecycle · Protocol reference
Install the runtime
Section titled “Install the runtime”[dependencies]arete-sdk = { package = "arete-a4-sdk", version = "0.51.2" }tokio = { version = "1", features = ["rt-multi-thread", "macros"] }futures = "0.3"anyhow = "1"The default TLS backend is rustls. To use native TLS:
arete-sdk = { package = "arete-a4-sdk", version = "0.51.2", default-features = false, features = ["native-tls"] }Generate the application package
Section titled “Generate the application package”Find a Rust-ready program or stack and install it into the project:
a4 explore catalog --query "<intent>" --target rust --jsona4 explore catalog stack <slug> --jsona4 install stack <slug> --rustUse a4 install program <slug> --rust for a standalone Program SDK. Read the
CLI output for the generated crate name and path; those depend on the project
configuration and dependency alias.
Connect to a generated stack
Section titled “Connect to a generated stack”use arete_sdk::prelude::*;use my_stack::MyStack;
#[tokio::main]async fn main() -> anyhow::Result<()> { let client = Arete::<MyStack>::builder() .secret_key(std::env::var("ARETE_API_KEY")?) .connect() .await?;
let positions = client.views.position.list().get().await; println!("{positions:?}");
client.disconnect().await; Ok(())}MyStack, position, and the generated crate path are placeholders. Use the
types and view accessors emitted for the installed package.
secret_key takes an agent key (a4_ak_...) or secret key (a4_sk_...) for
servers, agents and local scripts. With no auth option set, connect() uses
ARETE_API_KEY if it is set, and otherwise the key from your a4 login, so a
program on a machine logged in with a4 needs no key setup. Anything shipped to a browser uses an origin-bound
publishable key (publishable_key) instead, created with
a4 auth keys create-publishable --origin <scheme://host[:port]>.
Live views
Section titled “Live views”Every generated entity has its declared keyed and collection views. Derived views can add package-specific filters, sorting, and bounded windows.
Merged entities
Section titled “Merged entities”listen() yields current entity values with patches applied and removals
filtered out:
let mut positions = client.views.position.list() .listen() .take(10);
while let Some(position) = positions.next().await { println!("{position:?}");}Full update taxonomy
Section titled “Full update taxonomy”Use watch() when the application must distinguish a row changing, leaving
one query, or being deleted globally:
let mut updates = client.views.position.list() .watch() .filter("state.status", "open") .take(20) .with_snapshot_limit(100);
while let Some(update) = updates.next().await { match update { Update::Upsert { key, data } => println!("upserted {key}: {data:?}"), Update::Patch { key, data } => println!("patched {key}: {data:?}"), Update::Remove { key } => println!("{key} left this query"), Update::Delete { key } => println!("{key} was deleted globally"), }}Use watch_rich() when the generated view supports before/after diffs.
Subscriptions are lazy and reference-counted. Equivalent normalized queries share a wire subscription and unsubscribe when the final stream is dropped.
Program SDK
Section titled “Program SDK”Generated program modules expose pure instruction builders and PDA helpers.
The output is an Arete BuiltInstruction; no wallet or network is required:
use my_program::{self, DepositParams};
let instruction = my_program::deposit(DepositParams { owner: owner.clone(), amount: 1_000_000, ..Default::default()})?;
let (position, bump) = my_program::pdas::position(&owner)?;Connected stack clients expose the same generated program under
client.programs. Exact method and parameter names come from the generated
crate.
PDA derivation fills supported literal, argument, and account-reference seeds. Unknown parameters and missing required values fail closed.
Program Read
Section titled “Program Read”Generated program clients expose account readers tied to the exact installed release:
let position = client .programs .my_program .position_accounts()? .fetch(&position_address) .await?;Use the generated reader method rather than the placeholder above. Program Read is independent of the live view endpoint.
Generic chain reads
Section titled “Generic chain reads”let clock = client.chain().clock().await?;let balance = client .chain() .native_balance(&address, Default::default()) .await?;Use the chain surface for generic Solana state and the generated program reader for typed program accounts.
Transactions
Section titled “Transactions”The core SDK builds portable instructions but does not choose a Solana signing implementation. Attach a wallet adapter, then execute instructions or prepared operations:
let client = Arete::<MyStack>::builder() .secret_key(secret_key) .wallet(wallet) .connect() .await?;
let receipt = client .transaction(&[instruction], TransactionOptions::default()) .await?;
let receipt = client .execute(&prepared, ExecuteOptions::default()) .await?;The wallet compiles and signs locally. Execution classifies outcomes as
confirmed, definitely not submitted, submitted with unknown outcome, or failed
on chain. Do not automatically resend a submitted-unknown transaction.
Optional Solana adapter
Section titled “Optional Solana adapter”Enable the first-party adapter only when the application wants the SDK to build legacy, v0, or transaction-V1 messages:
arete-sdk = { package = "arete-a4-sdk", version = "0.51.2", features = ["solana-adapter"] }The adapter submits a signed transaction at most once. One deadline covers submission and confirmation. Direct RPC is an explicit transport selection; there is no silent hosted-to-direct fallback after an operation begins.
Sessions
Section titled “Sessions”Use a session when an application composes several generated stacks:
let session = Session::builder() .stack::<MarketsStack>("markets") .stack::<PositionsStack>("positions") .wallet(wallet) .connect() .await?;
let positions = session.stack::<PositionsStack>("positions")?;session.execute(&prepared, Default::default()).await?;session.close().await;Sessions share wallet and execution configuration while keeping each stack’s exact programs, views, and hosted bindings explicit.
HTTP-only mode
Section titled “HTTP-only mode”HTTP-only transport keeps Program Read, chain reads, point-in-time stack queries, and transaction execution available. Live view subscriptions fail fast because they require WebSocket transport.
Connection lifecycle
Section titled “Connection lifecycle”client.connection_state().await;let mut issues = client.subscribe_socket_issues();client.disconnect().await;Reconnects replay active subscriptions and apply an authoritative snapshot to replace local state. Preserve socket and schema-validation diagnostics in application logs.