Store and share a blob
Task: store a large binary (a file, an image) and make it available to other nodes in the context.
Blobs live outside CRDT state: you store the bytes once, get back a content
BlobId, keep that small id in your state, and announce the blob so peers can
fetch it. The replication model is in the
blobs reference.
The blob flow
Section titled “The blob flow”The SDK exposes a file-descriptor-style API in calimero_sdk::env:
| Step | Function | Returns |
|---|---|---|
| Open a new blob for writing | blob_create() | fd (u64) |
| Append bytes | blob_write(fd, &data) | bytes written |
| Finish writing | blob_close(fd) | BlobId ([u8; 32]) |
| Open an existing blob | blob_open(&blob_id) | fd |
| Read bytes | blob_read(fd, &mut buf) | bytes read |
Write path: blob_create → blob_write… → blob_close (the returned id is the
content hash). Read path: blob_open → blob_read… → blob_close.
Announce so peers can fetch
Section titled “Announce so peers can fetch”Storing a blob keeps it local. env::blob_announce_to_context(&blob_id, &context_id) advertises it to the rest of the context so other nodes can
discover and download it. This is apps/blobs:
use calimero_sdk::{app, env, BlobId};
pub fn upload_file(&mut self, name: String, blob_id: BlobId, size: u64) -> app::Result<String> { let current_context = env::context_id();
if env::blob_announce_to_context(blob_id.as_ref(), ¤t_context) { app::log!("Announced blob {} to network", blob_id); } else { app::log!("Warning: Failed to announce blob {}", blob_id); }
// keep the small id + metadata in CRDT state; the bytes stay in the blob store let file_id = format!("file_{}", self.file_counter.value()?); self.file_counter.increment()?; self.files.insert(file_id.clone(), /* FileRecord { blob_id, name, size, .. } */ )?; Ok(file_id)}The full arc: write the bytes to get a content id, announce that id so the rest of the context learns the blob exists, then any peer opens it by id and streams the bytes — recomputing the id to confirm it got what it asked for.
Exercise it
Section titled “Exercise it”# the BlobId comes back base58-encoded; store the metadata via your methodmeroctl --node node1 call upload_file \ --context <context-id> \ --args '{"name": "notes.txt", "blob_id": "<base58-blob-id>", "size": 12}'