Another important common collection is the storage map.
The type StorageMap<K, V> from the standard library stores a mapping of keys of type K to values of type V using a hashing function, which determines how it places these keys and values into storage slots. This is similar to Rust's HashMap<K, V>Icon Link but with a few differences.
Storage maps are useful when you want to look up data not by using an index, as you can with vectors, but by using a key that can be of any type. For example, when building a ledger-based sub-currency smart contract, you could keep track of the balance of each wallet in a storage map in which each key is a wallet’s Address and the values are each wallet’s balance. Given an Address, you can retrieve its balance.
Similarly to StorageVec<T>, StorageMap<K, V> can only be used in a contract because only contracts are allowed to access persistent storage.
StorageMap<T> is included in the standard library prelude which means that there is no need to import it manually.
Just like any other storage variable, two things are required when declaring a StorageMap: a type annotation and an initializer. The initializer is just an empty struct of type StorageMap because StorageMap<K, V> itself is an empty struct! Everything that is interesting about StorageMap<K, V> is implemented in its methods.
Storage maps, just like Vec<T> and StorageVec<T>, are implemented using generics which means that the StorageMap<K, V> type provided by the standard library can map keys of any type K to values of any type V. In the example above, we’ve told the Sway compiler that the StorageMap<K, V> in map will map keys of type Address to values of type u64.
Note two details here. First, in order to use insert, we need to first access the storage map using the storage keyword. Second, because insert requires writing into storage, a #[storage(write)] annotation is required on the ABI function that calls insert.
Icon InfoCircle
Note
The storage annotation is also required for any private function defined in the contract that tries to insert into the map.
Icon InfoCircle
Note
There is no need to add the mut keyword when declaring a StorageMap<K, V>. All storage variables are mutable by default.
Here, value1 will have the value that's associated with the first address, and the result will be 42. The get method returns an Option<V>; if there’s no value for that key in the storage map, get will return None. This program handles the Option by calling unwrap_or to set value1 to zero if map doesn't have an entry for the key.