One of the most attractive features of smart contracts is the possibility to store a substantial amount of data into them that can then be used in the contract code. Although Michelson provides different structures to store data, the object of this article is going to be its maps. Maps are hash tables that contain key/value pairs, which means that when you want to find a value in a map, you search for its key. This allows you to store complex data that can be referenced with a single word or number or even more complex data like a pair!
Unlike big maps, all the values in a map are deserialized, which allows developers to have access to all of them at once. While maps become more expensive to use when the number of key/value pairs increases, they are well-suited for smaller databases because of the extra features Michelson (like mapping or folding) and Taquito offer on maps.
Taquito reads maps in the storage of smart contracts and translates them into an instance of theMichelsonMap class. The class and its instances expose different features that give developers a lot of flexibility to use Michelson maps in their dapps. These features can be grouped into four groups:
- The instantiation: there are three different ways of creating a new MichelsonMap in Taquito
- The general methods: they give you information about the map, for example, its size or the elements it contains
- The key/value methods: they allow you to manipulate the keys and values in the map
- The update methods: they transform the map itself, for example by deleting elements or clearing out the map completely.
This tutorial is based on a simple smart contract deployed on Delphinet with a map that contains addresses as keys and tez as values. We will use all the methods available in Taquito’s MichelsonMap to check the map, extract values and modify them!
If you want to see all these functions in action, you can have a look at this Replit repo and click on the “Run” button.
Note: as Taquito is written in TypeScript, we will also use TypeScript to interact with the contract storage.
This paragraph is a little reminder of how to use Taquito to fetch the storage of a smart contract:
The setup code is pretty straightforward:
We import TezosToolkit and MichelsonMap from the @taquito/taquito package. We also import BigNumber from bignumber.js (the library is installed by Taquito) as TypeScript will need it for this particular example.
We instantiate the TezosToolkit object with the RPC address.
We fetch the contract using await Tezos.contract.at(contractAddress).
We extract the storage from the contract using the storage method on the ContractAbstraction object that was created one line above. We also type the storage variable with the MichelsonMap type which requires 2 type arguments: the type for the key and the type for the value (the address is basically a string and the tez will be converted to a BigNumber by Taquito).
Taquito provides three different ways of creating a new Michelson map: two of them can be used to create an empty map and the third one is used to create a map with default values.
The most simple way is to create an instance with no argument:
If you prefer, you can also pass an argument to the MichelsonMap constructor to indicate the type you want for the keys and the values:
Finally, you can also pass some values you want to create the instance with and let Taquito figure out the types using the fromLiteral static method:
The first thing you may want to check after fetching the data from a contract storage is if the part of the storage that you expect to be a map is indeed a map. This can be achieved by using the isMichelsonMap static method on the MichelsonMap class:
Note: this is a static method so you can use it without creating a new instance of MichelsonMap.
Once you are sure you are dealing with a map, you can check how many key/value pairs it holds with the size property:
Sometimes, you don’t want to do anything with the values in a map but you want to verify whether a key appears in the map, you can then use the has method and pass it the key you are looking for:
After that, you can fetch the value associated with the key you are looking for with the get method:
One of the main advantages of maps over big maps is that the key/value pairs are readily available in your dapp without any extra step. If you are looking for a simple solution to loop over all the pairs and get the key and the value, the MichelsonMap instance exposes a forEach method that allows you to get these values:
The code above will output:
The MichelsonMap instance exposes another method that will yield the same result, albeit in a different way. The entries method is a generator function that you can use if you wish to. This is how it works:
This code will yield the exact same result as the one above. A generator may be preferable according to your use case.
The same idea is available for keys and values, the keys and values methods are generators that will allow you to loop over the keys or the values of the map:
This example will output the following array containing all the keys of the map:
[ "tz1MnmtP4uAcgMpeZN6JtyziXeFqqwQG6yn6", "tz1R2oNqANNy2vZhnZBJc8iMEqW79t85Fv7L", "tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb", "tz1aSkwEot3L2kmUvcoxzjMomb9mvBNuzFK6" ]
Similarly, you can use values instead of keys to output some or all the values in the map:
This will output all the values of the map inside an array:
[ 789000000, 912000000, 123000000, 456000000 ]
Although reading and organizing the keys or the values fetched from a Michelson map is a common use case, you may also want to modify a map, for example, before originating a new contract. Taquito also thought about it and provides different methods that will help you add or remove key/value pairs from a map.
First, you can use the set method to add a new value to an instance of MichelsonMap:
This adds a new entry in the map with the address being the first argument and the BigNumber being the value.
Note: it is important to use new BigNumber(345) for the value and not simply 345 as TypeScript will throw a type error because earlier, we set the type argument of the MichelsonMap to BigNumber.
You can also delete one of the entries of the map with the delete method:
Note: deleting a key that doesn’t exist doesn’t throw an error, it will just have no effect on the map.
To finish, you can also delete all the entries in a Michelson map if you want with the clear method:
If you want to know more about MichelsonMap and some advanced usages (for example, how to use pairs as the map keys), you can learn in the advanced tutorial available in the Taquito documentation.
- The Best Crypto Trading Bots
- Deribit Review | Options, Fees, APIs and Testnet
- FTX Crypto Exchange Review
- The Best Bitcoin Hardware wallet
- Crypto Copy Trading Platforms
- The Best Crypto Tax Software
- Best Crypto Trading Platforms
- Best Crypto Lending Platforms
- Ledger vs Trezor
- BlockFi vs Celsius vs Hodlnaut
- Bitsgap review — A Crypto Trading Bot That Makes Easy Money
- Quadency Review- A Crypto Trading Bot Made For Professionals
- PrimeXBT Review | Leverage Trading, Fee and Covesting
- HaasOnline Review and Get a 10% discount
- The Idiots Guide to Margin Trading on Bitmex
- eToro Review | Trade Stocks, Crypto, ETFs, CFDs, and commodities
- BlockFi Review | Earn up to 8.6% interests on your Crypto
- Best Crypto APIs for Developers
- Best Blockchain Analysis Tools
- Crypto arbitrage guide: How to make money as a beginner
- Top Bitcoin Node Providers
- Best Crypto Charting Tool
- What are the best books to learn about Bitcoin?