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.1.1). The
SDK is not yet published to npm, so install it from source for now.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 from Source
viem (v2.21+) is a required peer dependency.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.
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 | Description |
|---|---|---|---|
| Aeneid | "testnet" | https://aeneid.storyrpc.io | 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.
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 |
ObserverRequiredError | OBSERVER_REQUIRED | Auto-querying globalPubKey / threshold without an observer |
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 |
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 |
RpcConsensusError | RPC_CONSENSUS | Validation RPCs disagree about a DKG value |
ContractRevertError | CONTRACT_REVERT | On-chain transaction reverted |
CDRError, which has a code property for programmatic handling:

