uploadCDR/accessCDRfor small secrets stored directly on-chainuploadFile/downloadFilefor larger encrypted files stored off-chain
Prerequisites
- CDR SDK setup complete with WASM initialized and client created
What Runs On-Chain vs Off-Chain
Encrypt a Secret
The diagram below shows the on-chain secret flow: allocate a vault, encrypt the secret locally with TDH2, and write the ciphertext to the vault.
msg.sender equals the configured condition address, so only that wallet can
write or read the vault. Because the high-level uploadCDR() helper validates
that condition addresses point at deployed condition contracts, EOA conditions
are configured through the low-level allocate() call with
skipConditionValidation: true.
Any EOA address works as a write or read condition; only that EOA can
perform the matching action. To gate just one side, set your wallet address
on that side and a condition contract (such as
LicenseReadCondition) on the
other. The high-level uploadCDR() helper expects deployed condition
contracts on both sides and does not support EOA conditions, so use it for
patterns like DATA Foundation license-gated reads (see IP Asset
Vaults) and use the low-level
allocate() + write() flow above for owner-only EOA conditions.The value of the transaction must be exactly the same as the fee.
dataKey is the historical parameter name. In encryptDataKey() it can be
any secret bytes, not just a cryptographic key.Decrypt a Secret
Decryption requires submitting a read request on-chain, collecting partial decryptions from validators, and combining them client-side.
accessCDR() auto-generates the ephemeral keypair and auto-queries
globalPubKey when you omit them. The threshold is derived automatically
from the partial-decryption bucket’s DKG round.The timeout of the request on the server side is 200 blocks, which is
approximately 7 minutes. If you’re not able to collect enough partials within
this timeout, try another read request.
Advanced: Manual Keypair Control
Advanced: Manual Keypair Control
Encrypt and Download a File


uploadFile() helper requires deployed condition contracts on both sides,
so the example below uses DATA Foundation’s OwnerWriteCondition for the write side and
LicenseReadCondition for the read side. License token holders can decrypt
the file (see IP Asset Vaults for the
end-to-end license setup). For an owner-only file flow, replicate the
low-level steps shown earlier with your wallet (EOA) address as both
conditions.
HeliaProvider is the only storage backend fully tested on Aeneid in the
current release, and it requires Node.js 22+.uploadFile() and downloadFile() work with raw file bytes. In a browser,
start from a File object and convert it with new Uint8Array(await file.arrayBuffer()).Storage Providers
The encrypted-file workflow supports four storage backends:HeliaProviderfor in-process IPFS. This is the best starting point for development and the only backend fully tested on Aeneid so far.GatewayProviderfor an external IPFS HTTP API plus a gateway URL.StorachaProviderfor Storacha /web3.storage.SynapseProviderfor Filecoin-backed storage via Synapse.
If you use
HeliaProvider, pass the CID.parse function into the constructor
as shown above to avoid class mismatches.Step-by-Step (Low-Level)
If you need more control over the process, you can call each step individually.These snippets continue from the variables in the examples above:
walletClient, globalPubKey, requesterPubKey, recipientPrivKey, and
dataKey.Encrypt (Low-Level)
Decrypt (Low-Level)
Query DKG State
You can query DKG state and fees without a wallet or WASM initialization:Understanding Fees
Each CDR operation has an on-chain fee:
Fees are paid in native tokens (wei) and are sent as
msg.value with each transaction.