The Graph: Building a subgraph with The Sandbox

Jonathan Limtiaco
Async
Published in
5 min readApr 25, 2022

Recently I started working with The Graph and realized learning web3 technologies isn’t as daunting as one might think. The Graph is a decentralized protocol for indexing and querying data from blockchains. It provides developers a way to store data from smart contract events and then query that data with a standard GraphQL API. In this article we’ll create a subgraph that uses The Sandbox’s ASSET and LAND contract and does the following:

  • Indexes two smart contracts (ASSET and LAND)
  • Listens for Transfer events
  • Creates a Token record for each Transfer event using the event data

We’ll cover everything from the project setup to the deployment of the subgraph. I’ll admit having some experience with GraphQL reduced the learning curve but finish this article and you’ll be ready to create subgraphs for your next dapp.

Setup

First, you’ll need to create a subgraph studio project which you can do in the subgraph studio by connecting your wallet and then clicking the “Create a Subgraph” button. Next you’ll need to install the Graph CLI which you can do by running the command below.

npm install -g @graphprotocol/graph-cli

Initialization

Now that we have everything needed to get started we can init a subgraph project by running the command below.

graph init --index-events --contract-name <NameDescribingContract> --product subgraph-studio --from-contract <ContractAddress>

After running this command you’ll be prompted to enter your subgraph name/slug which you can find on the subgraph studio page you just created (see image below). You’ll now be able to accept all the defaults for the prompts that follow.

Write Subgraph

After completing the previous steps we should have a generated subgraph project which we can edit as we see fit. There are three main files — which we’ll cover in the upcoming sections — that we’ll be dealing with when making changes.

  • schema.graphql
  • subgraph.yaml
  • mapping.ts

Schema.graphql

The schema.graphql file is where we’ll define the data we want stored (entities) and how that data will look. Later, we’ll be able to query anything we define here once our subgraph is deployed. Here is an example of my schema.graphql file which defines entity Token with fields id, tokenId, collection, and owner .

type Token @entity {
id: ID!
tokenId: BigInt!
collection: String!
owner: String!
}

Subgraph.yaml

The subgraph.yaml file defines what smart contracts your subgraph indexes, which events to listen for, which mapping function to call for each event, and the entities that’ll be created in the schema.graphql file. One thing to highlight in the yaml file is we can add the field startBlock which tells the subgraph which block to start the indexing (I recommend adding this field so your subgraph syncs faster).

specVersion: 0.0.2
schema:
file: ./schema.graphql
dataSources:
- kind: ethereum
name: Land
network: mainnet
source:
address: "0x50f5474724e0Ee42D9a4e711ccFB275809Fd6d4a"
abi: Land
startBlock: 9048219
mapping:
kind: ethereum/events
apiVersion: 0.0.5
language: wasm/assemblyscript
entities:
- Token
abis:
- name: Land
file: ./abis/Land.json
eventHandlers:
- event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransferLand
file: ./src/mapping.ts

We currently have our subgraph setup to index one smart contract but what if we need our subgraph to index two smart contracts? This can easily be done by adding another dataSource. In the example below we added a second dataSource and updated the following fields:

  • address — the second smart contract address
  • startBlock —the contract creation block which can be found on etherscan
  • entities — the entities that will be created from the event data
  • abis file —the abi for this smart contract which can be found on etherscan
  • eventHandlers event — the event we want to listen for
  • eventHanlders handler — the function we want to call whenever the event happens

Note: I also updated all references of the contract name (Land to Asset)

specVersion: 0.0.2
schema:
file: ./schema.graphql
dataSources:
- kind: ethereum
name: Land
network: mainnet
source:
address: "0x50f5474724e0Ee42D9a4e711ccFB275809Fd6d4a"
abi: Land
startBlock: 9048219
mapping:
kind: ethereum/events
apiVersion: 0.0.5
language: wasm/assemblyscript
entities:
- Token
abis:
- name: Land
file: ./abis/Land.json
eventHandlers:
- event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransferLand
file: ./src/mapping.ts
- kind: ethereum
name: Asset
network: mainnet
source:
address: "0x067a1Eb5E383eD24b66D72aAf80d8D7dB3d299A8"
abi: Asset
startBlock: 9040032
mapping:
kind: ethereum/events
apiVersion: 0.0.5
language: wasm/assemblyscript
entities:
- Token
abis:
- name: Asset
file: ./abis/Asset.json
eventHandlers:
- event: Transfer(indexed address,indexed address,indexed uint256)
handler: handleTransferAsset
file: ./src/mapping.ts

Mapping.ts

In our mapping.ts file we’ll create our event handlers and use the event data to create our entities that we defined in our schema.graphql file. In my example I have a function called handleTransferLand and handleTransferAsset which is called anytime there is a Transfer event and creates a Token entity using _tokenId and _to from the event params.

import { Transfer as TransferEvent } from "../generated/Land/Land"
import { Token } from "../generated/schema"
export function handleTransferLand(event: TransferEvent): void {
const id = `${event.params._tokenId}-LAND`
let entity = new Token(id)
entity.tokenId = event.params._tokenId
entity.collection = "LAND"
entity.owner = event.params._to.toHexString()
entity.save()
}
export function handleTransferAsset(event: TransferEvent): void {
const id = `${event.params._tokenId}-ASSET`
let entity = new Token(id)
entity.tokenId = event.params._tokenId
entity.collection = "ASSET"
entity.owner = event.params._to.toHexString()
entity.save()
}

Deploy Subgraph

Now that we have made all the changes we want, we’re ready to deploy our subgraph. Before we do that though lets make sure our types are up-to-date and compile the subgraph to WebAssembly by running the command below.

graph codegen && graph build

Next we’ll authenticate using our deploy key and deploy using our subgraph slug. You’ll be able to find your deploy key and subgraph slug on your subgraph studio page which we created in the “Setup” section.

graph auth  --studio <DeployKey>graph deploy --studio <SubgraphSlug>
A sample query using the playground that gets the first token and the response

We now have a subgraph deployed successfully and you’re ready to start making queries in the playground or in your dapp. To learn more about The Graph head over to the docs and look out for the next article.

Check out the entire project on Github here
https://github.com/jrlimtiaco/sandbox

Check out the deployed subgraph here
https://thegraph.com/studio/subgraph/sandbox/

--

--