TypeScript SDK guide
@lumi-node/locus-sdk is a faithful TypeScript port of the Rust locus-client
crate. PDA derivation, instruction layouts, and query/result hashing all match
byte-for-byte, so attestations produced from TypeScript are identical to those
produced from Rust.
It has two usage modes:
- Read-only / browser-safe —
getProtocolUsage, the account decoders, andArmsClientneed no signer and bundle cleanly for the browser. The homepage counter uses exactly these. - Write paths —
LocusClientmethods take an explicitKeypairsigner.
Install
npm install @lumi-node/locus-sdk @solana/web3.js
getProtocolUsage(connection, programId?)
Aggregate, on-chain-attested usage. Returns:
interface ProtocolUsage {
agents: number; // # AgentMemory accounts
totalReads: bigint; // Σ read_count — attested retrievals
totalWrites: bigint; // Σ write_count — memory commits
attestations: number; // # RetrievalAttestation accounts
lastActivity: number | null; // latest last_updated (unix seconds)
}
It works by filtering getProgramAccounts on each account’s Anchor discriminator,
then decoding the counters — no IDL or backend required.
ArmsClient
Typed wrapper over the ARMS REST API: place, get, query, stateRoot,
healthz. See the ARMS REST API page.
LocusClient
const locus = new LocusClient(connection, {
programId, // optional, defaults to the deployed program
armsEndpoint, // optional, defaults to http://localhost:8080
});
PDA helpers
const [agentPda] = locus.agentPda(ownerPubkey);
const [attestationPda] = locus.attestationPda(agentPda, version, nonce);
Reads
const agent = await locus.getAgentMemory(ownerPubkey); // AgentMemory | null
const att = await locus.fetchAttestation(attestationPda); // RetrievalAttestation | null
Writes (require a Keypair)
await locus.initializeAgent(owner, readFeeLamports, metadataUri);
await locus.commitMemory(owner, rootBytes); // Uint8Array(32)
await locus.updateReadFee(owner, newFee);
Attested retrieval
const result = await locus.queryWithAttestation(requester, agentOwner, embedding, k);
// result.neighbors, result.signature, result.attestationPda,
// result.queryHash, result.resultHash, result.version, result.nonce
This hits ARMS /query, hashes the query and result the same way the Rust SDK
does, then records a RetrievalAttestation on-chain (paying the agent’s read fee).
Low-level instruction builders
Every write also has a pure instruction builder (initializeAgentIx,
commitMemoryIx, updateReadFeeIx, attestRetrievalIx) returning a
TransactionInstruction, so you can compose them into your own transactions or a
wallet-adapter flow.
Hashing utilities
import { hashEmbedding, hashNeighbors } from "@lumi-node/locus-sdk";
Both return a 32-byte Uint8Array and match the Rust implementation exactly.