Skip to main content

Getting Started with Storage Programs

This guide walks you through creating a Storage Program, writing data to it, and reading it back over RPC.

Prerequisites

  • Bun (latest) installed
  • The Demos SDK: bun add @kynesyslabs/demosdk@latest
  • A Demos wallet with enough balance to cover storage fees (1 DEM per 10 KB chunk, minimum 1 DEM)
  • Access to a Demos Network RPC node

The mental model

Every Storage Program operation follows the same four-step shape:
  1. Build a typed payload with one of the StorageProgram.* static helpers (createStorageProgram, writeStorage, updateAccessControl, deleteStorageProgram, plus the granular setField / setItem / appendItem / deleteField / deleteItem).
  2. Sign it with demos.storagePrograms.sign(payload) — this returns a signed Transaction.
  3. Confirm gas with demos.confirm(tx).
  4. Broadcast with demos.broadcast(validityData) (or demos.broadcastAndWait for deterministic inclusion).
Reads are different — they go through demos.storagePrograms.read(address) directly, no transaction required.

Step 1: Connect

demos.getAddress() is synchronous and returns the connected wallet’s address as a string. It does not return a Promise.

Step 2: Build the create payload

StorageProgram.createStorageProgram(deployer, programName, data, encoding, acl?, options) builds the payload for the create transaction. The deterministic storage address is derived inside the helper — you don’t compute it separately.
options.nonce is required. It is the sender’s current account nonce, fetched via demos.getAddressNonce(ownerAddress). Without it the helper throws "nonce is required for storage program creation". The nonce is mixed into the address derivation so each create from the same deployer produces a unique address even when programName collides.

Step 3: Sign, confirm, broadcast

See Broadcasting a Transaction for the difference between broadcast and broadcastAndWait and the error types each can throw.

Step 4: Write data

writeStorage replaces the entire data field of the program. For surgical updates use the granular operations below.

Step 5: Read data

Reads are served directly over RPC — no transaction, no fee.
The full response shape is StorageProgramResponse from @kynesyslabs/demosdk/storage. Notable fields: owner, programName, encoding, data, metadata, storageLocation, sizeBytes, createdAt, updatedAt. See RPC Queries for queries beyond the address-based lookup.

Granular updates

For JSON-encoded programs, you can change individual fields and array elements without rewriting the whole document:
Each returns a StorageProgramPayload you sign + confirm + broadcast like any other write. Granular operations are JSON-only — they are rejected for binary-encoded programs.

Updating access control and deleting

Both return payloads that follow the same sign / confirm / broadcast flow.

Fees

Storage Programs are billed at 1 DEM per 10 KB chunk, minimum 1 DEM per write. Calculate the fee for a payload before sending it:
The fee is returned as a bigint in OS (1 DEM = 10⁹ OS). See Amounts & Denominations for the conversion helpers.

Resource limits

Where to go next

  • Operations — when to use create vs. write vs. granular ops, and the full lifecycle.
  • Access Controlowner / public / restricted modes, allowlists, blacklists, and group permissions.
  • RPC Queries — full read-side surface, including the node-level RPC endpoints for listing, searching, and field-level lookups.
  • API Reference — every StorageProgram static helper, payload shape, and response interface.
  • Cookbook — end-to-end recipes (public profile, team workspace, binary attachments).