Cosmos Quick Start

... 2022-6-23 About 6 min

# Cosmos Quick Start

In this Quick start guide, we're going to start with a simple Cosmos starter project in the Juno Network and then finish by indexing some actual real data. This is an excellent basis to start with when developing your own SubQuery Project.

If your are looking for guides for Substrate/Polkadot, you can read the Substrate/Polkadot specific quick start guide.

At the end of this guide, you'll have a working SubQuery project running on a SubQuery node with a GraphQL endpoint that you can query data from.

If you haven't already, we suggest that you familiarise yourself with the terminology used in SubQuery.

The goal of this quick start guide is to adapt the standard starter project to begin indexing all votes on the Terra Developer Fund (opens new window) (which also contributed to SubQuery) from Cosmos, it should only take 10-15 minutes

You can see the final code of this project here at https://github.com/jamesbayly/juno-terra-developer-fund-votes (opens new window)

# Preparation

# Local Development Environment

# Install the SubQuery CLI

Install SubQuery CLI globally on your terminal by using NPM:

# NPM
npm install -g @subql/cli
1
2

Please note that we DO NOT encourage the use of yarn global for installing @subql/cli due to its poor dependency management which may lead to an errors down the line.

You can then run help to see available commands and usage provide by CLI

subql help
1

# Initialise the SubQuery Starter Project

Cosmos is not yet supported in SubQuery's CLI (subql), to start with Juno clone or fork the starter project (opens new window).

After the initialisation process is complete, you should see a folder with your project name has been created inside the directory. The contents of this directoy should be identical to what's listed in the Directory Structure.

Last, under the project directory, run following command to install the new project's dependencies.

cd PROJECT_NAME
yarn install
1
2
cd PROJECT_NAME
npm install
1
2

# Making Changes to your Project

In the starter package that you just initialised, we have provided a standard configuration for your new project. You will mainly be working on the following files:

  1. The GraphQL Schema in schema.graphql
  2. The Project Manifest in project.yaml
  3. The Mapping functions in src/mappings/ directory

The goal of this quick start guide is to adapt the standard starter project to begin indexing all transfers from the bLuna smart contract.

# Updating your GraphQL Schema File

The schema.graphql file defines the various GraphQL schemas. Due to the way that the GraphQL query language works, the schema file essentially dictates the shape of your data from SubQuery. Its a great place to start becuase it allows you to define your end goal up front.

We're going to update the schema.graphql file to read as follows so we can index all votes on the Terra Developer Fund (opens new window).

type Vote @entity {
  id: ID! # id field is always required and must look like this
  blockHeight: BigInt!
  voter: String! # The address that voted
  proposalID: BigInt! # The proposal ID
  vote: Boolean! # If they voted to support or reject the proposal
}
1
2
3
4
5
6
7

Important: When you make any changes to the schema file, please ensure that you regenerate your types directory. Do this now.

yarn codegen
1
npm run-script codegen
1

You'll find the generated models in the /src/types/models directory. For more information about the schema.graphql file, check out our documentation under Build/GraphQL Schema

# Updating the Project Manifest File

The Projet Manifest (project.yaml) file can be seen as an entry point of your project and it defines most of the details on how SubQuery will index and transform the chain data.

We won't do many changes to the manifest file as it already has been setup correctly, but we need to change our handlers. Remember we are planning to index all votes on the Terra Developer Fund (opens new window). This means that we we will look at messages that use the vote contract call, we need to update the datasources section to read the following.

dataSources:
  - kind: cosmos/Runtime
    startBlock: 3246370 # The block when the first proposal in this fund was created
    mapping:
      file: "./dist/index.js"
      handlers:
        - handler: handleTerraDeveloperFund
          kind: cosmos/MessageHandler
          filter:
            type: "/cosmwasm.wasm.v1.MsgExecuteContract"
            # Filter to only messages with the vote function call
            contractCall: "vote" # The name of the contract function that was called
            values: # This is the specific smart contract that we are subscribing to
              contract: "juno1lgnstas4ruflg0eta394y8epq67s4rzhg5anssz3rc5zwvjmmvcql6qps2"
1
2
3
4
5
6
7
8
9
10
11
12
13
14

This means we'll run a handleTerraDeveloperFund mapping function each and every time there is a vote message from the Terra Developer Fund (opens new window) smart contract.

For more information about the Project Manifest (project.yaml) file, check out our documentation under Build/Manifest File

# Add a Mapping Function

Mapping functions define how chain data is transformed into the optimised GraphQL entities that we have previously defined in the schema.graphql file.

Navigate to the default mapping function in the src/mappings directory. You'll see four exported functions, handleBlock, handleEvent, handleMessage, and handleTransaction. Since we are dealing only with messages, you can delete everything other than the handleMessage function.

The handleMessage function recieved event data whenever event matches the filters that we specify previously in our project.yaml. We are going to update it to process all vote messages and save them to the GraphQL entity that we created earlier.

You can update the handleMessage function to the following (note the additional imports and renaming the function):

import { Vote } from "../types";
import { CosmosMessage } from "@subql/types-cosmos";

export async function handleTerraDeveloperFund(
  message: CosmosMessage
): Promise<void> {
  // logger.info(JSON.stringify(message));
  // Example vote https://www.mintscan.io/juno/txs/EAA2CC113B3EC79AE5C280C04BE851B82414B108273F0D6464A379D7917600A4

  const voteRecord = new Vote(`${message.tx.hash}-${message.idx}`);
  voteRecord.blockHeight = BigInt(message.block.block.header.height);
  voteRecord.voter = message.msg.sender;
  voteRecord.proposalID = message.msg.msg.vote.proposal_id;
  voteRecord.vote = message.msg.msg.vote.vote === "yes";

  await voteRecord.save();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

What this is doing is receiving a CosmosMessage which includes message data on the payload. We extract this data and then instantiate a new Vote entity that we defined earlier in the schema.graphql file. We add additional information and then use the .save() function to save the new entity (SubQuery will automatically save this to the database).

For more information about mapping functions, check out our documentation under Build/Mappings

# Build the Project

In order run your new SubQuery Project we first need to build our work. Run the build command from the project's root directory.

yarn build
1
npm run-script build
1

Important: Whenever you make changes to your mapping functions, you'll need to rebuild your project

# Running and Querying your Project

# Run your Project with Docker

Whenever you create a new SubQuery Project, you should always run it locally on your computer to test it first. The easiest way to do this is by using Docker.

All configuration that controls how a SubQuery node is run is defined in this docker-compose.yml file. For a new project that has been just initalised you won't need to change anything here, but you can read more about the file and the settings in our Run a Project section

Under the project directory run following command:

yarn start:docker
1
npm run-script start:docker
1

It may take some time to download the required packages (@subql/node (opens new window), @subql/query (opens new window), and Postgres) for the first time but soon you'll see a running SubQuery node. Be patient here.

# Query your Project

Open your browser and head to http://localhost:3000 (opens new window).

You should see a GraphQL playground is showing in the explorer and the schemas that are ready to query. On the top right of the playground, you'll find a Docs button that will open a documentation draw. This documentation is automatically generated and helps you find what entities and methods you can query.

For a new SubQuery starter project, you can try the following query to get a taste of how it works or learn more about the GraphQL Query language.

query {
	votes(
    first: 5
    orderBy: BLOCK_HEIGHT_DESC
    # filter: {proposalID: {equalTo: "4"}}
  ) {
    nodes {
      id
      blockHeight
      voter
      vote
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

You can see the final code of this project here at https://github.com/jamesbayly/juno-terra-developer-fund-votes (opens new window)

# Publish your SubQuery Project

SubQuery provides a free managed service when you can deploy your new project to. You can deploy it to SubQuery Projects (opens new window) and query it using our Explorer (opens new window).

Read the guide to publish your new project to SubQuery Projects

# Next Steps

Congratulations, you now have a locally running SubQuery project that accepts GraphQL API requests for transfers data from bLuna.

Now that you've had an insight into how to build a basic SubQuery project, the question is where to from here? If you are feeling confident, you can jump into learning more about the three key files. The manifest file, the GraphQL schema, and the mappings file under the Build section of these docs.

Otherwise, continue to our Academy section where have more in depth workshops, tutorials, and example projects. There we'll look at more advanced modifications, and we'll take a deeper dive at running SubQuery projects by running readily available and open source projects.

Finally, if you're looking for more ways to run and publish your project, our Run & Publish section provides detailed informatation about all the ways to run your SubQuery project and other advanced GraphQL aggregation and subscription features.

Last update: June 23, 2022 09:54