Basics

Containers

`cw-storage-plus`` provides several storage containers that can be used to store data on the blockchain. The fundamental ones are:

An Item is a simple container that stores a single value. The other two are a little more involved - they are collections capable of storing multiple values, and provide several methods to interact with them.

Keys and prefixes

One task of a storage library like cw-storage-plus is to manage the namespace of keys provided by the blockchain.

When constructing a container, you must provide a key of type &'static str (or use new_dyn (opens in a new tab)). This usually means you'll be providing a string literal or some constant.

In the case of an Item, the provided string is the exact key (a standard UTF-8 string) under which the value will be saved. In the case of collections, the provided string is a prefix (sometimes called namespace in the code); the collection will use this prefix to generate keys (by appending to it) for the individual values it stores.

As a contract dev, it is your responsibility to ensure that the keys you provide are unique and do not conflict with keys used by other parts of the contract.

💡

Over time, we've learned that using long keys hurts storage performance. If you gotta go fast, a good approach might be to only provide single-character ASCII prefixes for your containers, like "a", "b", "c", etc.

Generally speaking, we tried to make it so that as long as you use a unique prefix for each container, you shouldn't have to worry about key conflicts.

TODO: Research the key collisions in the warning below more! Then we can provide better advice.

⚠️

...yet there's a small but. A Map's prefix is length-prefixed. An Item is saved without any sort of length-prefixing of the key. It is, in theory, possible for an Item's key to conflict with one of the keys generated by a Map or Deque. In practice, this is unlikely unless you use very long prefixes or start your Item's key with the null byte. Probably don't do that!

Values

In cw-storage-plus, every value is saved using JSON serialization. For that to be possible, only types that implement serde::Serialize (opens in a new tab) and serde::Deserialize (opens in a new tab) are allowed.

Most of the Rust standard library types already implement these traits. Additionally, types you'll find in cosmwasm_std (like Addr (opens in a new tab), Decimal (opens in a new tab), Binary (opens in a new tab) or Coin (opens in a new tab)) often do as well.

If you're writing a custom type and wish to send it across call or put it in storage, you'll have to derive these traits.

💡

cw-storage-plus uses serde-json-wasm (opens in a new tab) under the hood. This provides determinism in some corners - serde_json (opens in a new tab) would not be suited for the blockchain world! On top of that, serde-json-wasm is just smaller.