Skip to content

Model your data

Task: store a piece of your app’s data in a field of #[app::state], and read and write it from a method.

Every field of your state is a CRDT from calimero_storage::collections. Pick the one whose merge behaviour matches the data — that single choice decides how concurrent edits on different nodes converge.

You have…UseImport
A keyed map of valuesUnorderedMap<K, V>calimero_storage::collections::UnorderedMap
A growable listVector<V>calimero_storage::collections::Vector
A map you iterate in key order / by rangeSortedMap<K, V>calimero_storage::collections::SortedMap
A count many nodes bumpCounter (grow-only) / PNCounter (also decrements)calimero_storage::collections::Counter
A single value, last-writer-winsLwwRegister<T>calimero_storage::collections::LwwRegister

See Collections for the full list and the exact merge rule of each.

This is apps/kv-store — an UnorderedMap whose values are LwwRegister<String>:

use calimero_sdk::app;
use calimero_storage::collections::{LwwRegister, UnorderedMap};
#[app::state]
pub struct KvStore {
items: UnorderedMap<String, LwwRegister<String>>,
}
#[app::logic]
impl KvStore {
#[app::init]
pub fn init() -> KvStore {
KvStore { items: UnorderedMap::new() }
}
// write: `value.into()` builds the LwwRegister<String>
pub fn set(&mut self, key: String, value: String) -> app::Result<()> {
self.items.insert(key, value.into())?;
Ok(())
}
// read: `get` returns a read-only ValueRef; clone out the inner value
#[app::view]
pub fn get(&self, key: String) -> app::Result<Option<String>> {
Ok(self.items.get(&key)?.map(|v| v.get().clone()))
}
}

Key things the snippet shows:

  • Construct fields with ::new() inside #[app::init].
  • Every accessor returns a Result — collection reads and writes can fail, so use ?.
  • get hands back a read-only reference; .get().clone() pulls the value out of the LwwRegister. To mutate in place, use get_mut.
Terminal window
meroctl --node node1 call set \
--context <context-id> --args '{"key": "hello", "value": "world"}'
meroctl --node node1 call get \
--context <context-id> --args '{"key": "hello"}'