Documentation Index
Fetch the complete documentation index at: https://docs.kynesys.xyz/llms.txt
Use this file to discover all available pages before exploring further.
RPC Queries
Storage Program reads are served over plain RPC. They cost nothing, require no transaction, and typically come back in well under 100 ms. This page covers the read surface only — for write flow see Operations.Two read paths
| You want | Use |
|---|---|
| The full program for a known address | demos.storagePrograms.read(address) — the SDK shortcut |
| Anything else (list by owner, search, field-level lookup, type/exists checks) | demos.rpcCall({ method, params }) against one of the 9 node endpoints below |
demos.storagePrograms.list(), .search(), or .getField(). To call those, drop down to demos.rpcCall(...).
The SDK’s
read helper attaches the wallet’s identity automatically (via signMessage) when a wallet is connected. ACL is enforced server-side: anonymous callers see only public programs; restricted/owner programs require the requesterAddress (passed implicitly by read, explicitly by rpcCall) to be in the ACL.Reading a single program
GET <rpc>/storage-program/<address> and, when a wallet is connected, attaches identity: ed25519:<address> and signature: <ed25519-sig> headers. The node uses those headers to resolve the requester for ACL.
StorageProgramResponse shape
This is the actual response interface from @kynesyslabs/demosdk/storage:
Read-time access control
success: false plus an errorCode is how access denials surface. The SDK does not throw on ACL rejection — it returns a structured response. Always branch on result.success before reading result.data.
The 9 node RPC endpoints
All of these are reached viademos.rpcCall({ method, params: [{ message, data, muid }] }). The message is the endpoint name; the data object carries the parameters. Most endpoints accept an optional requesterAddress for ACL — pass demos.getAddress() when you have a connected wallet and want non-public programs to resolve.
rpcCall returns an RPCResponse with shape { result: number, response: any, require_reply: boolean, extra: any }. result is an HTTP-style status code (200 on success, 400/403/404/500 on failure). The actual payload lives on response. When a program is missing or soft-deleted, the node returns 200 / null (not 404) for single-program reads.1. getStorageProgram — full program by address
Same data the SDK’s read helper returns, but reachable via rpcCall if you’d rather not go through the HTTP route.
response is StorageProgramData (or null) — a slightly richer cousin of StorageProgramResponse that adds createdByTx, lastModifiedByTx, and interactionTxs[].
2. getStorageProgramAll — full program (alias)
Despite the name, this is not a “list everything” endpoint. It takes a storageAddress and returns full StorageProgramData for that one program — kept as an alias of getStorageProgram for SDK back-compat. Same params, same response shape.
3. getStorageProgramsByOwner — list by owner (paginated)
Server-side pagination is pushed into SQL — limit and offset apply before deserialization, so very large owner sets remain cheap. ACL is filtered in the same SQL pass: callers who are not the owner see only programs they have read access to.
null. Items are StorageProgramListItem, the lighter shape (no data, no metadata, no owner — owner is implied because you queried for it).
4. getStorageProgramFields — top-level field names
JSON-only. Returns the keys of the top-level object.
StorageProgramFieldsResponse interface exported from @kynesyslabs/demosdk/storage. Binary-encoded programs return 400 / INVALID_FIELD_TYPE.
5. getStorageProgramFieldType — JSON type of a single field
JSON-only. Returns one of "string" | "number" | "boolean" | "array" | "object" | "null" | "undefined" (StorageFieldType).
404 / FIELD_NOT_FOUND.
6. getStorageProgramValue — single field value
JSON-only. Returns the field’s value plus its inferred JSON type.
demos.storagePrograms.read(address, key) overload.
7. getStorageProgramItem — array element by index
JSON-only. Supports negative indexing (-1 is the last item).
400 / INDEX_OUT_OF_BOUNDS. Field exists but is not an array returns 400 / INVALID_FIELD_TYPE.
8. hasStorageProgramField — existence check
JSON-only. For binary or non-object data the node returns exists: false rather than an error — it treats non-object data as having no fields.
getStorageProgramValue when you only need to know whether a field is present — it never throws on missing fields.
9. searchStoragePrograms — name search with ACL
Partial match by default. ACL is filtered at the SQL layer, so anonymous callers transparently see only public programs and paginated results are full pages (no post-fetch JS filter that would silently shorten them).
StorageProgramListItem shape.
Higher-level convenience: StorageProgram static helpers
If you’d rather not assemble nodeCall envelopes yourself, the StorageProgram class exposes a parallel set of static async query methods that wrap the same RPC endpoints. They take an rpcUrl directly and return strongly-typed responses (or null on error). See API Reference for the full list — StorageProgram.getByAddress, getByOwner, searchByName, getFields, getValue, getItem, hasField, getFieldType, getAll.
Demos instance — just an RPC URL — which makes them convenient for read-only/server-side code.
Performance & batching
Reads are RPC-only: no transaction, no fee, no consensus round-trip. Typical latency is sub-100 ms against a healthy node.Parallelize independent reads
Use updatedAt as a staleness signal
StorageProgramResponse.updatedAt is the canonical “did anything change?” field — it’s an ISO 8601 timestamp set on every successful write. Cache aggressively against it rather than polling the full document:
read(address) and a comparison against your cached updatedAt.
Field-level reads avoid full-document transfer
When you only need one key out of a 500 KB program, usegetStorageProgramValue (or StorageProgram.getValue) instead of read — the node serializes only the requested field, not the whole document.
Error handling
| Surface | How it shows up |
|---|---|
| Program not found / soft-deleted | success: false (or result.response === null over rpcCall) |
| ACL denial | success: false with an errorCode |
| Wrong encoding for a JSON-only endpoint | 400 / INVALID_FIELD_TYPE |
| Field missing | 404 / FIELD_NOT_FOUND |
| Array index out of bounds | 400 / INDEX_OUT_OF_BOUNDS |
| Bad params | 400 with error describing the missing/invalid field |
| Server error | 500 / INTERNAL_ERROR |
storagePrograms.read, StorageProgram.getByAddress, etc.) never throw on these — they return a structured response (or null). For full payload details on individual error codes, see node docs.
See also
- Getting Started — create / write / read flow end-to-end
- Operations — write-side surface (granular updates, deletes, ACL changes)
- Access Control — how
owner/public/restrictedmodes interact with read ACL - API Reference — every static helper, payload, and response interface
- Cookbook — end-to-end recipes