Documentation Index
Fetch the complete documentation index at: https://docs.story.foundation/llms.txt
Use this file to discover all available pages before exploring further.
These docs track the Aeneid release of
@piplabs/cdr-sdk (v0.2.1).Prerequisites
- Node.js 18+ and npm 8+
- Node.js 22+ if you plan to use
HeliaProvider - A funded wallet on Aeneid testnet
- viem (v2.21+) for blockchain interactions
Install
viem (v2.21+) is a required peer dependency.Storage providers are optional and pull their own peer dependencies. Install
them only for the backend you use:
helia, multiformats, and
@helia/unixfs for HeliaProvider, @storacha/client for StorachaProvider,
or @filoz/synapse-sdk for SynapseProvider.If you plan to mint Story license tokens in an IP-gated flow, also install
@story-protocol/core-sdk.Initialize WASM
The CDR SDK uses a WebAssembly module for threshold cryptography. You must initialize it once before performing any encryption or decryption operations.In a React application, initialize WASM in a provider component or top-level
effect so it’s ready before any CDR operations are attempted.
Browser and Bundler Guidance
- Vite / webpack - Import the SDK from normal ESM application code and call
initWasm()before the first encryption or decryption. If your SSR build tries to evaluate the SDK server-side, move the import behind a client-only boundary. - Next.js / SSR - Keep browser wallet flows in
"use client"components. For route handlers or scripts that use CDR cryptography, run them in the Node runtime instead of Edge. - Edge runtime - The current release is not documented for Edge runtimes. Prefer the browser or Node.js runtime on Aeneid.
- TypeScript - Use modern ESM resolution.
moduleResolution: "Bundler"is a good default for browser apps;moduleResolution: "NodeNext"fits pure Node ESM projects.
Story-API REST Endpoint
EveryCDRClient requires an apiUrl — the base URL of a Story-API REST
endpoint. The SDK reads all DKG state (active round, global public key,
threshold, participant count, registered validators, and validator
attestations) over this REST API. Contract state such as vaults and fees is
still read over the EVM publicClient.
| Network | Story-API REST URL | Notes |
|---|---|---|
| Aeneid | http://172.192.41.96:1317 | Plain HTTP. May change between deployments. |
For production deployments you can point
apiUrl at your own Story node’s
REST gateway instead of the shared endpoint. Configure it through an
environment variable so it is easy to swap.Create the CDR Client
TheCDRClient provides three sub-clients:
observer- Read-only queries (fees, vault data, DKG state). Always available.uploader- Encryption and vault allocation. Requires awalletClient.consumer- Decryption and read requests. Requires awalletClient.
In React (Wallet Connector)
In a React app, you typically get the wallet from a connector like Privy, RainbowKit, or wagmi. Create a read-onlyCDRClient up front, and build a write-capable client on demand from the wallet’s provider.
hooks/use-cdr-client.ts
With Private Key (Backend / Scripts)
For server-side code, scripts, or CLI tools, you can use a private key directly:Read-Only (No Wallet)
If you only need to query vault data or DKG state, you can omit thewalletClient:
Network Configuration
Supported Network
| Network | network param | Default RPC URL | Story-API REST URL | Description |
|---|---|---|---|---|
| Aeneid | "testnet" | https://aeneid.storyrpc.io | http://172.192.41.96:1317 | Current supported release |
Testnet
Custom RPC URL
You can point the SDK to any Aeneid-compatible RPC endpoint by changing thehttp() transport URL. This is useful for third-party RPC providers with
higher rate limits. The apiUrl is configured independently — point it at the
shared Story-API endpoint or your own Story node’s REST gateway.
Using Environment Variables
A common pattern is to configure the network via environment variables:config.ts
.env
Quick Start: End-to-End Secret Example
The script below creates an owner-only vault, writes a small secret, then reads it back with the same wallet. It is fully runnable onceWALLET_PRIVATE_KEY is
set.
quickstart-cdr.ts
This example sends three transactions total:
allocate(), write(), and
read(). For larger payloads, switch to uploadFile() / downloadFile()
with deployed condition contracts (such as the Story license-gated pattern
in IP Asset Vaults).Any EOA address works as a write or read condition — only that EOA can
perform the matching action. The high-level
uploadCDR() / uploadFile()
helpers validate that condition addresses point at deployed contracts, so
EOA conditions go through the low-level allocate() call with
skipConditionValidation: true.Next Steps
- For network-side runtime behavior, see Runtime Configuration.
- For the main integration flows, continue to Encrypt & Decrypt.
Error Handling
The SDK throws typed errors you can catch and handle:| Error Class | Code | When |
|---|---|---|
CDRError | varies | Base class for all SDK-specific errors |
WalletClientRequiredError | WALLET_CLIENT_REQUIRED | Accessing uploader or consumer without a walletClient |
InvalidParamsError | INVALID_PARAMS | Invalid parameter combinations, such as only passing one keypair parameter |
InvalidConditionContractError | INVALID_CONDITION_CONTRACT | Condition address does not implement the required interface |
LabelMismatchError | LABEL_MISMATCH | Ciphertext label does not match the vault UUID |
ContentSizeExceededError | CONTENT_SIZE_EXCEEDED | Encrypted data exceeds maxEncryptedDataSize |
EmptyVaultError | EMPTY_VAULT | Reading a vault that has never been written to |
PartialCollectionTimeoutError | PARTIAL_COLLECTION_TIMEOUT | collectPartials or accessCDR times out waiting for validator responses |
CidIntegrityError | CID_INTEGRITY | Downloaded encrypted file does not match the vault CID |
On-chain transaction reverts (for example, a failed condition check) surface
as the underlying
viem contract errors, not a CDR-specific error class.CDRError, which has a code property for programmatic handling:

