Working with Maps and BigMaps

Learn how to:

  • Fetch data from a Map datatype on a Tezos Smart Contract
  • Fetch data from a BigMap datatype on a Tezos Smart Contract
  • Initialize Map data while originating a new contract to the Tezos Blockchain
  • Use Pairs as a key to access Map and BigMap values
  • Why Michelson Map and BigMap don't look like a Javascript Map

Taquito provides MichelsonMap, which makes it easy and familiar for developers to work with the native Michelson map datatypes. MichelsonMap supports initialization, get and set methods to Maps using primitive datatypes and pairs as keys.

Michelson offers two variants of Maps that are semantically the same but have different implementations and trade-offs in terms of gas and storage costs on a contract. A Map will use more storage but cost less gas, whereas a BigMap will consume less storage but has higher gas costs during the execution of the Smart Contract.

A Contract with a single Map for storage

Origination of the contract with an initial storage

This example builds on the Ligo Lang Taco Shop learning resources.

The storage of the contract used in the following example is a map where a key is a natural number (a nat), and a value is a pair composed of two values representing the quantity of stock and tez tokens respectively. The source code of the contract is available here. In the example, the contract is originated with initial values using the MichelsonMap class' set method.

Live Editor
Result

The fromLiteral convenience method can be used instead of using set for each element. Here is the same origination operation but using fromLiteral to create our MichelsonMap.

Live Editor
Result

Accessing the values of the map

This example loads the same type of Taco Shop contract (we created this one earlier). Taquito provides a get method of the MichelsonMap on storage of type Map, and in this case, we access the value stored with a key of 1.

Then, the example calls the Contracts main function of the contract using the key 1 as its parameter. Remember, we can only change contracts storage by calling the function provided by the contract. The main function on this Smart Contract has the effect of decreasing the value of the current_stock associated with the key 1. The get method of the MichelsonMap class is used again to see the difference in storage after the method call.

Live Editor
Result

A Contract with a Map using an unannotated pair/tuple as a key

Here we have the storage of our contract defined in Michelson.

It has a Map with the annotated name %theMap. This Map uses a pair consisting of a natural number and an address as its key (1, tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx). Its value is also a pair of values, consisting of an int (annotated as %quantity) and mutez (annotated as %amount).

(pair (pair (address %theAddress)
(map %theMap (pair nat address) (pair (mutez %amount) (int %quantity))))
(int %theNumber))

Origination of the contract with Pair as Map keys

Since the key of the map has no annotations, MichelsonMap requires that we use an index value starting at 0 to initialize its elements.

Live Editor
Result

Accessing Map values using Pairs

The get method of the MichelsonMap class can be used to access values of the map for a specified key.

This example accesses the map using its theMap annotation. If the storage does now annotate its properties, the caller must use numeric indexes instead.

Recall that this contract does not annotate the pairs of the key pair either, we use numeric indexes for this also.

Live Editor
Result

A Map with nested Pairs as keys

This contract schema has a key with eight nested pairs and value of an int. This example type of key is impractical, but we offer it as an example to illustrate how to work with complex keys.

The Michelson storage schema with a map using eight pairs as a key:

(map (pair int
(pair nat
(pair string
(pair bytes
(pair mutez
(pair bool
(pair key_hash
(pair timestamp address)))))))) int)

Origination a contract with complex keys

The contract schema in this example does not have map annotations which means that each value needs to have an index as a property name.

Live Editor
Result

Accessing Map values with complex keys

The get method of the MichelsonMap class accesses values of the map for a specified key.

Live Editor
Result

BigMaps

Map and BigMap are semantically the same (except one difference), everything you learned about Maps applies to working with BigMap's. The only difference is that when calling get on a BigMap will return a Javascript Promise whereas get on a Map returns directly.

Contract storage containing a map and a bigMap

The MichelsonMap class also supports the bigMap type. The following example uses a contract containing both a map and a bigMap in its storage. Here is the Michelson definition of storage for this example:

(pair (big_map %thebigmap (pair nat address) int) (map %themap (pair nat address) int))

Origination of the contract with an initial storage

Live Editor
Result

Accessing the values of the map and the bigMap

The get method of the MichelsonMap class accesses the values of the map and values of the bigMap. The difference is that for a map, the value gets returned directly while the get method on a bigMap returns a promise.

Live Editor
Result