# The Graph Tutorial: Creating a Subgraph

By [Naveen](https://paragraph.com/@naveen) · 2022-02-15

---

Before you continue, I'm assuming you know what [The Graph](https://thegraph.com/) is and what problems it tackles. If you haven't, I highly recommend checking out - [Why The Graph](https://mirror.xyz/0xB38709B8198d147cc9Ff9C133838a044d78B064B/VCVxxsQpGeNKJfe6EYtR7JuT_Ilgt5iMdeqTjJB2jec).

Installation
------------

First of all, you'll need **Graph CLI** tool. Install it via:

**yarn**

    yarn global add @graphprotocol/graph-cli
    

or, **npm**

    npm install -g @graphprotocol/graph-cli
    

In this tutorial, I'll be using a simple [Gravity](https://github.com/graphprotocol/example-subgraph/blob/master/contracts/Gravity.sol) contract as an example.

Before you can use the already installed Graph CLI, head over to the [Subgraph Studio](https://thegraph.com/studio/) and connect your account. You'll need a wallet like [MetaMask](https://metamask.io/) already installed on your browser. So make sure it is there.

Time to create a new subgraph in the studio now. Note that the Gravity contract is already deployed on Ethereum Mainnet. You can inspect it on [Etherscan](https://etherscan.io/address/0x2e645469f354bb4f5c8a05b3b30a929361cf77ec#code). It is deployed at the following address:

With this information known, go ahead and create a new subgraph in the studio. Select the Ethereum Mainnet as the network to index the contract data from. And fill-in a sensible name of subgraph like - `Gravity`. Hit continue. This will take you to the dashboard where you may fill optional fields like description, website, etc. I'm gonna skip it for sake of brevity.

Initializing Subgraph
---------------------

The Graph CLI provides `graph init` command to initialize the subgraph:

    graph init \
      --product subgraph-studio
      --from-contract <CONTRACT_ADDRESS> \
      [--network <ETHEREUM_NETWORK>] \
      [--abi <FILE>] \
      <SUBGRAPH_SLUG> [<DIRECTORY>]
    

I recommend checking what each option does by running `graph init --help` in console.

Now copy the generated subgraph slug from the dashboard. It is `gravity` for me. We need it for initializing this subgraph:

    graph init --studio gravity
    

_(Note that_ `--studio` option above is nothing but short-hand for `--product subgraph-studio`)

This will prompt for multiple inputs like network name, contract address, ABI etc. In this case, we're using the Ethereum Mainnet network, with an already deployed Gravity contract. Make sure your input match the following:

    ✔ Protocol · ethereum
    ✔ Subgraph slug · gravity
    ✔ Directory to create the subgraph in · gravity
    ✔ Ethereum network · mainnet
    ✔ Contract address · 0x2E645469f354BB4F5c8a05B3b30A929361cf77eC
    ✔ Fetching ABI from Etherscan
    ✔ Contract Name · Gravity
    

If not provided inline to `graph init`, the cli will try to fetch the ABI of the contract from Etherscan. If not found, you'll need to provide a path to the ABI file of the contract. ABI is easy to generate for your contract through dev tools like [Hardhat](https://hardhat.org/) or [Truffle](https://trufflesuite.com/), one of which you might already be using. Or, you can simply copy it from IDE, if you're using [Remix](https://remix.ethereum.org/). In our case, ABI was already available on Etherscan.

Initialization creates a new directory containing multiple auto-generated files for you as a starting point. These include some configuration files specifically tailored for the provided contract through its ABI. Open this project in your favorite editor and let's start with the next steps.

Configuring Subgraph Manifest
-----------------------------

The subgraph manifest file - `subgraph.yaml` is a [YAML](https://circleci.com/blog/what-is-yaml-a-beginner-s-guide/) file located at the root path. This describes the data sources your subgraph will index. In this case, the data source is the Gravity contract on Ethereum Mainnet. Replace the contents of the file with:

    specVersion: 0.0.4
    description: Gravatar for Ethereum
    repository: https://github.com/graphprotocol/example-subgraph
    schema:
      file: ./schema.graphql
    dataSources:
      - kind: ethereum/contract
        name: Gravity
        network: mainnet
        source:
          address: '0x2E645469f354BB4F5c8a05B3b30A929361cf77eC'
          abi: Gravity
          startBlock: 6175244
        mapping:
          kind: ethereum/events
          apiVersion: 0.0.6
          language: wasm/assemblyscript
          entities:
            - Gravatar
          abis:
            - name: Gravity
              file: ./abis/Gravity.json
          eventHandlers:
            - event: NewGravatar(uint256,address,string,string)
              handler: handleNewGravatar
            - event: UpdatedGravatar(uint256,address,string,string)
              handler: handleUpdatedGravatar
          file: ./src/mapping.ts
    

We're gonna keep this simple. You can find out about what each of the available fields mean at full specification [here](https://github.com/graphprotocol/graph-node/blob/master/docs/subgraph-manifest.md). Though some notable ones are:

*   `schema.file`: Path to a GraphQL schema file defining what data is stored for your subgraph. This also generated with initialization.
    
*   `dataSources`: List of sources from which to index data. You can use a single subgraph to index the data from multiple smart contracts.
    
*   `dataSources.source`: Address and ABI of the source smart contract. `startBlock` indicates from which block of the blockchain to start indexing data. Its value is usually the block at which the contract was deployed.
    
*   `dataSources.mapping.entities`: These are the entities that are written to The Graph network's storage. These entities are defined in a GraphQL schema file - `schema.graphql`.
    
*   `dataSources.mapping.abis`: ABI files for the source contract as well as any other smart contracts that you interact with from within the mappings (`mapping.ts` file that you will write).
    
*   `dataSources.mapping.eventHandlers`: List of the smart-contract events that this subgraph will react to with corresponding handlers that are defined in mappings file (`./src/mapping.ts`). It is these handlers that will transform the events to proper entities to be saved.
    
*   `dataSources.mapping.callHandlers` (not used here): Lists of the smart-contract functions the subgraph reacts to with corresponding handlers. These handlers are defined in the mapping too. They transform the inputs and outputs to function calls into entities in the store.
    
*   `dataSources.mapping.blockHandlers` (not used here): Blocks with handlers the subgraph will react to. With no `filter` it will react every time new block is appended to chain. However, a `call` filter will make the handler run only if the block contains at least one call to the data source contract.
    

Defining Entities
-----------------

The entities are defined in a GraphQL schema file - `schema.graphql`, also located the root path. These entities indicate what data is stored for this subgraph and how to query it. If you're new to GraphQL, check out at least a primer on it on [official website](https://graphql.org/learn/) or if you're feeling adventurous like me try this [awesome course](https://odyssey.apollographql.com/) by Apollo team.

Alright, I assume you have at least basic knowledge of GraphQL by now. But before defining entities think about the structure of your data, like how you would've done while designing schemas for a DB. All the queries made from user-facing app will me made against this data model. **Rather than imagining these entities in smart-contract lingo i.e. imagining entities as "events" or contract "functions", imagine entities as data "objects".** Your app will query on these objects.

In our case, for example, it can be seen in `subgraph.yaml` above that, the network is instructed to react to `NewGravatar`/`UpdateGravatar` through handlers - `handleNewGravatar`/`handleUpdateGravatar` (defined in `mapping.ts`). These handlers eventually convert event data to a related entity (`Gravatar`) defined in `schema.graphql`, which will then be saved/updated in storage. Here the entity is the `Gravatar` object, not the individual events. A good schema would be:

    type Gravatar @entity {
      id: ID!
      owner: Bytes
      displayName: String
      imageUrl: String
    }
    

Open the `schema.graphql` and paste above to finish defining the entity.

Writing Mappings
----------------

The job of the mappings file (in `./src/mapping.ts`) is to convert data coming from the blockchain (e.g. events) to an entity defined in the `schema.graphql` and write it to store. The mappings are written in [AssemblyScript](https://www.assemblyscript.org/) which can be compiled to [WASM](https://webassembly.org/). It is a stricter subset of [TypeScript](https://www.typescriptlang.org/). If you've never written any TypeScript ever, I recommend getting familiar with the syntax [here](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html).

All the APIs available to write these mappings are described in [AssemblyScript API](https://thegraph.com/docs/en/developer/assemblyscript-api) docs. You might want to check out at least [Built-in Types](https://thegraph.com/docs/en/developer/assemblyscript-api#built-in-types) and [Store API](https://thegraph.com/docs/en/developer/assemblyscript-api#store-api) specifically to start.

If you inspect `./src/mapping.ts`, you can see already pre-filled code that was generated by the `graph init` command ran earlier. But this is based off the `subgraph.yaml` and `schema.graphql` before editing. Since we changed contents of these two we need to generate types corresponding to updated entities. This is so we can use these generated types/classes to write our `mapping.ts`. The Graph CLI provides the `codegen` command for this purpose. Run:

_(This is also pre-configured in_ `package.json` so that you can run `yarn codegen` or `npm codegen` which does the same)

You can see the generated types/classes corresponding to schema as well as source contract(s) in the `./generated` directory.

Alright, now is the time to write the handlers - `handleNewGravatar` and `handleUpdateGravatar` that were specified at `dataSources.mapping.eventHandlers` in the `subgraph.manifest`. Open the `mapping.ts` and replace with following:

    // Import event classes
    import {
      NewGravatar,
      UpdatedGravatar
    } from "../generated/Gravity/Gravity";
    
    // Import entity class
    import { Gravatar } from "../generated/schema";
    
    export function handleNewGravatar(event: NewGravatar): void {
      // Use id field from emitted event as unique id for the entity
      const id = event.params.id.toHex();
    
      // Create a new Gravatar Entity with unique id
      const gravatar = new Gravatar(id);
    
      // Set Gravatar Entity fields
      gravatar.owner = event.params.owner;
      gravatar.displayName = event.params.displayName;
      gravatar.imageUrl = event.params.imageUrl;
    
      // Save entity to store
      gravatar.save();
    }
    
    export function handleUpdatedGravatar(event: UpdatedGravatar): void {
      // Use proper id to load an entity from store
      const id = event.params.id.toHex();
    
      // Load the entity to be updated
      let gravatar = Gravatar.load(id);
    
      // Create the entity if it doesn't already exist
      if (!gravatar) {
        gravatar = new Gravatar(id);
      }
    
      // Set updated fields to entity
      gravatar.owner = event.params.owner;
      gravatar.displayName = event.params.displayName;
      gravatar.imageUrl = event.params.imageUrl;
    
      // Save updated entity to store
      gravatar.save();
    }
    

Note the imports above are the same types/classes generated earlier by `graph codegen`. The handlers receive `event` of type `NewGravatar`/`UpdateGravatar`, which are subclass of a parent `ethereum.Event` class. The event data fields is available in `event.params` object.

Each entity requires a unique id assigned to it. Here, hex of `event.params.id` (type `BigInt`) from contract event is used. However, uniqueness can also be guaranteed by choosing id from event metadata like:

*   `event.transaction.from.toHex()`
    
*   `event.transaction.hash.toHex() + "-" + event.logIndex.toString()`
    

After setting/updating fields to entity, [Store API](https://thegraph.com/docs/en/developer/assemblyscript-api#store-api) provides methods like `load` and `save` on `Entity` (inherited by `Gravatar`) types to retrieve and save the entity to store.

Publishing the Subgraph
-----------------------

Now that all of the configuration is done, let's proceed to deploying this subgraph. But before doing that make sure that `mapping.ts` is checked without any errors or bugs. It is not checked by code generation step. As a necessary precaution run the build command:

_(Or_ `yarn build` / `npm build` as this command must also be configured in `package.json` too)

This compiles the subgraph to WebAssembly. If there is a syntax error somewhere, it should fail. Otherwise, build succeeds, creating a `./build` directory with built files.

For deploying the subgraph to [Subgraph Studio](https://thegraph.com/studio/), you'll need the deploy key of the subgraph. Go to the already created Gravity subgraph's dashboard in the studio and copy its **deploy key**. Now authenticate from cli with this key:

    graph auth --studio <DEPLOY KEY>
    

This stores the access token to system's keychain.

Finally, deploy to studio by providing subgraph slug:

    graph deploy --studio gravity
    

This will ask for a version label for current version of your subgraph. You can enter whatever version semantic you prefer or go with `v0.0.1`.

    ✔ Version Label (e.g. v0.0.1) · v0.0.1
    .
    .
    ✔ Apply migrations
    ✔ Load subgraph from subgraph.yaml
    .
    ✔ Compile subgraph
    .
    ✔ Write compiled subgraph to build/
    .
    .
    ✔ Upload subgraph to IPFS
    

Note that the subgraph is not yet published! It is currently deployed to the studio. After deployment it will start syncing data from the chain and take some time, after which you can play around and test it. Then, if everything seems to be ok, hit **Publish**. This will publish your subgraph to the production on the Graph network and you'll get an API endpoint, like below, where you query the data:

    https://api.studio.thegraph.com/query/<ID>/<SUBGRAPH_NAME>/<VERSION>
    

Note that every query will be **charged in GRT tokens** as fees.

However, for testing purposes the studio also provides a temporary, rate limited API endpoint. For example, for me it was - `https://api.studio.thegraph.com/query/21330/gravity/v0.0.1`. Let's see if it works. You can use this online GraphQL client - [GraphiQL](https://graphiql-online.com/) for that. Enter your testing API endpoint and make the following query to get a gravatar by id and hit run:

    query MyQuery {
      gravatar(id: "0xa") {
        displayName
        id
        imageUrl
        owner
      }
    }
    

which outputs:

    {
      "data": {
        "gravatar": {
          "displayName": "duqd",
          "id": "0xa",
          "imageUrl": "https://ucarecdn.com/ddbebfc0-...",
          "owner": "0x48c89d77ae34ae475e4523b25ab01e363dce5a78"
        }
      }
    }
    

It worked!

This was a fairly simple example to familiarize with the workings of The Graph. You might define a more complex GraphQL schema, mappings and the subgraph manifest for a production application. Feel free to dive into the [official docs](https://thegraph.com/docs/en/developer/quick-start/) for reference.

See full code at GitHub repo [here](https://github.com/theNvN/gravity-subgraph).

_Hope you learned some awesome stuff! 😎_

_Feel free to catch me_ [_here_](https://linktr.ee/thenvn)_!_

---

*Originally published on [Naveen](https://paragraph.com/@naveen/the-graph-tutorial-creating-a-subgraph)*
