The Mercury Quickstart.

Start indexing your data in minutes with our interactive quickstart tutorial.

1. Introduction

The Quickstart tutorial serves as the initial step in the onboarding process for Mercury users. Whether you are an expert develoepr or not, the quickstart will get you up to speed with how Mercury works and by the end you will have enough knowledge of all the basics required to start building your apps integrating network data seamlessly and efficiently. You will be guided step by step along the process, so hold on until the end!

Data Indexing

Data indexing allows developers to retrieve on-chain data efficiently in order to display it on their clients. This is a crucial feature for services and decentralized apps which use the on-chain data for their user interfaces or even internal logic. For example, let's assume you're developing a lending protocol: you will want to display from the webapp the actions of a user in the protocol, the growth/evolution of the supplies, etc. In order to retrieve such data efficiently, you will either have to rely on your own infrastructure or rely on an indexing service such as Mercury. You can read more about the use of indexers in the ecosytem and how Mercury achieves its efficiency in the "Data Access After Protocol 20: How and Why Mercury (and Zephyr) Addresses Evolving Data Needs." event recap.

What You Will Do

Along this quickstart you will interact with and index a deployed pool contract (or edit it thorugh Okashi and redeploy it if you'd like) which allows to deposit and withdraw liquidity, though for simplicity without actually making any token transfers. The contract will also emit events for each deposit and withdrawal. The goal of this quickstart is to end up building an interface to display all the events and monitor the liquidity of the pool.

2. The Contract

As mentioned, the contract is very simple and not particularly useful, but it still allows to showcase part of the functionality offered by Mercury while still keeping everything simple. Below you can see the contract code and functions, and copy the deployed contract address. This is powered by the Okashi.dev editor.

Note: there's a temporary bug in the Okashi editor which prevents you from directly deploying and interacting with the contract on Testnet. For now you can use this contract address: CD7ESBY7XTZFGDGZPBKQAFFAJP7PPLDJLIC2QPKYJQVDZRMKLRZ6O7DD

Now that you've taken a glance at the contract, you can better understand the data structures we're going to index with Mercury. For the sake of testing though, in this quickstart we will only index the deposits and the supply evolution. This is because we want to showcase one of the features of Mercury which is the ability to perform not only granular queries, but also granular subscriptions.

Subscriptions

Subscriptions is a concept we've introduced in Mercury in order to maintain a very lightweight infrastructure while still offering all the advantages of working with a managed indexing service. In order to start indexing your data on Mercury, you need to make a subscription to it before. In our situation, we only want to index deposit events, which while it'is counter-intuitive in this specific example (there's really no reason we wouldn't want withdraw events indexed), shines light on the ability to perform granular subscriptions.

While with Mercury you can potentially subscribe to all events of a contract, in many cases it's not what you're really looking for. For instance, imagine a liquidations interface which, among 30 protocols, only needs to read liquidation events. If the interface were to index all events for all the 30 protocols it'd be storing a lot of data which isn't needed and which has an impact on the pricing.

3. Making the Subscriptions

Now that you understand the concept of subscriptions, you can subscribe to the deposit contract events and to the evolution of the supply. The easier way to create a subscription is from our webapp, but first you will have to generate the XDR representation of the topics you want to subscribe to (as it's the one that you're going to insert as parameter). Let's break down this process step by step.

Deposit event

Looking at the docs, to subscribe to contract events you need to specify the contract address and the wanted topics in their XDR representation. In our case we want the "deposit" events, and we know that "deposit" is the first topic. To craft the correct XDR, we need to generate the ScVal for the "deposit" symbol and then convert it to base64 xdr. Below is a runkit script to generate the XDR:

If you run the above script you should see AAAADwAAAAdkZXBvc2l0AA== as result, and that's the XDR we're going to use.

Mercury WebApp Subscription

Now let's create our first subscription! If you haven't already, sign up in the Mercury testnet webapp, and then head to your home.

Once you're in the home, click on the "New Subscription" button and select contract events. Now insert the contract id (as mentioned before, you can copy paste it from Okashi) and set as topic1 the topic generated by the above snippet, so AAAADwAAAAdkZXBvc2l0AA==.vr headsetAfter clicking "subscribe" you should be welcomed by a "Subscribed Successfully" text and be able to see the subscription in the webapp's home.

Ledger Entry Subscription

We also want to track the DataKey::Supply value within our contract. This value is kept in the contract instance, so this means that we need to subscribe to the contract's instance ledger entry. To craft the correct XDR, we need to generate the ScVal for the contract instance key and then convert it to base64 xdr. Below is a runkit script to generate the XDR:

If you run the above script you should see AAAAFA== as result, and that's the XDR we're going to use when crafting the ledger entry subscription.

Mercury WebApp Subscription

This time we need to create a ledger entry subscription, so go ahead and click on the "New Subscription" button and select "Ledger Entries". Now insert the contract id and set as "Key XDR" the key generated by the above snippet, so AAAAFA==. Set the durability to persistent (because contract instances are persistent entries) and tick "hydrate" so that Mercury knows you also want to index the current value for the instance. To learn more about the different options you have when subscribing, jump to our docs.vr headsetAfter clicking subscribe you should be welcomed by a "Subscribed Successfully" text and be able to see the subscription in the webapp's home.

4. Querying

You're now in the last step of the quickstart, which is also the most fun as you will see all the previous parts coming together. If you've followed up to here by deploying your own contact, you might want to make some interactions with it in order to produce some data to query. But you can also use the already deployed contract above. Querying is done through the Mercury GraphQL API.

As the docs mention, to index our events and ledger entries we can craft this GraphQL query, see https://docs.mercurydata.app/queries/contract-events and https://docs.mercurydata.app/queries/contract-data-entry-updates.

Mercury GraphiQL

Mercury offers a graphiql endpoint, which is a playground for interacting with the graphql API where you will be able to play around with queries and customize them according to your needs. You can go ahead and open the GraphiQL endpoint.

Before sending the query above, you need to authorize yourself for access to the Mercury database. Go to the "keys" page in the webapp, insert your email and password to get an access token and keep a copy of it safe. Note that these currently expire every week for security purposes, but this will change soon.

Once you have your key you can add it as a GraphQL auth header (look at the bottom of the picture below) and make your query!

Note: the txinfo for the just-retrieved current entry update will be null.

vr headset

Understanding the Returns

As a result of your query you're now going to see some return data. From the first query you should be returned all the events for the specified contract that you're subscribed to: in our case, we have subscribed only to the "deposit" events of our contract, that is the contrct events which present "deposit" as "topic 1". If you were to make a withdraw and make again the same query, even if the withdraw event was emitted by the same contract, it wouldn't appear as you didn't subscribed to it.

From the second query you're going to be returned instad the updates of the ledger entry you subscribed to. As you can see we're using the query "entryUpdateByContractId": that means that the query will return all the updates of all the entries you have subscribed to for the provided contract. In our case we only are subscribed to one entry for this specific contract (the contrcat instance entry which points only to the key "supply"), so it's fine to use this query if we just want the "supply" updates as a return. Nevertheless, if you are subscribed to more entries for the same contract and you just need the updates for a specific entry, it's also possible to make more specific queries and filter the updates through keys (see the docs).

Parsing returns

Besides the contract ids and ledger [info] numbers, everything else is base64-encoded XDR data (aside from transaction hashes, those are just base64 encoded hashes). This means that you now need to parse the contract event topics, data, and the instance itself.

Below is a simple script to help you in parsing these from the client-side in Javascript. If you paste the XDR correctly you will be returned the parsed contract data from the events and the value of the key "supply" from the contract instance.

Conclusion

Parsing the returned data on the client side is the last step of the process. On the documentation you can find more exmples on how to parse the different return values provided by the Mecury GrapQL endpoint (soon there will be a dedicated section on data parsing). Now you know the basics on how to build your first dapp reliant on Mecury. Of course there are many different variations when you adapt the workflow to your specific indexing needs, but the general pattern is always the same. In our documentation (which will be constantly improved), you will find everything you need to know about indexing various types of data. Fon any other doubt that you have you can join and ask on our discord server. Happy indexing!