What’s Subgraph and The Components of a Subgraph

SeanHuang
6 min readNov 16, 2020

--

This is a document for the semi-technical beginners of theGraph project. It will give an overall introduction of subgraph, specifying what subgraph is and the components of a subgraph project.

What’s Subgraph

A subgraph defines which data The Graph will index from Ethereum, and how it will store it. Once deployed, it will form a part of a global graph of blockchain data. The subgraph definition consists of a few files:

·subgraph.yaml: a YAML file containing the subgraph manifest

·schema.graphql: a GraphQL schema that defines what data is stored for your subgraph, and how to query it via GraphQL

·AssemblyScript Mappings: AssemblyScript code that translates from the event data in Ethereum to the entities defined in your schema

We’ll further explore the three files in detail.

The Subgraph Manifest(Subgraph.yaml)

The subgraph manifest subgraph.yaml defines the smart contracts your subgraph indexes, which events from these contracts to pay attention to, and how to map event data to entities that Graph Node stores and allows to query. An example of subgraph.yaml:

Subgraph.yaml

Meaning of each field:

·description: a human-readable description of what the subgraph is. This description is displayed by the Graph Explorer when the subgraph is deployed.

·repository: the URL of the repository where the subgraph manifest can be found. This is also displayed by the Graph Explorer.

·dataSources.source: the address of the smart contract the subgraph sources, and the abi of the smart contract to use. The address is optional; omitting it allows to index matching events from all contracts.

·dataSources.source.startBlock: the optional number of the block that the data source starts indexing from. In most cases we suggest using the block in which the contract was created.

·dataSources.mapping.entities: the entities that the data source writes to the store. The schema for each entity is defined in the the schema.graphql file.

·dataSources.mapping.abis: one or more named ABI files for the source contract as well as any other smart contracts that you interact with from within the mappings.

·dataSources.mapping.eventHandlers: lists the smart contract events this subgraph reacts to and the handlers in the mapping — ./src/mapping.ts in the example — that transform these events into entities in the store.

·dataSources.mapping.callHandlers: lists the smart contract functions this subgraph reacts to and handlers in the mapping that transform the inputs and outputs to function calls into entities in the store.

·dataSources.mapping.blockHandlers: lists the blocks this subgraph reacts to and handlers in the mapping to run when a block is appended to the chain. Without a filter, the block handler will be run every block. An optional filter can be provided with the following kinds: call. A call filter will run the handler if the block contains at least one call to the data source contract.

A single subgraph can index data from multiple smart contracts. Add an entry for each contract from which data needs to be indexed to the dataSources array.

The GraphQL Schema

A GraphQL schema that defines what data is stored for your subgraph, and how to query it via GraphQL. The schema for your subgraph is in the file schema.graphql.

Defining Entities(What data to store for subgraph?)

All queries will be made against the data model defined in the subgraph schema and the entities indexed by the subgraph. Because of this, it is good to define the subgraph schema in a way that matches the needs of your dApp. It may be useful to imagine entities as “objects containing data”, rather than as events or functions.With The Graph, you simply define entity types in schema.graphql.

Entities Defining

Defining Fulltext Search Fields(How to query data stored?)

Fulltext search queries filter and rank entities based on a text search input. Fulltext queries are able to return matches for similar words by processing the query text input into stems before comparing to the indexed text data.

A fulltext query definition includes the query name, the language dictionary used to process the text fields, the ranking algorithm used to order the results, and the fields included in the search. Each fulltext query may span multiple fields, but all included fields must be from a single entity type.

To add a fulltext query, include a _schema_ type with a fulltext directive in the GraphQL schema.

An fulltext query example:

Fulltext Query

We now define an entity which can be searched by the fulltext query above.

The example bandsearch field can be used in queries to filter band entities based on the text documents in the name, description, and bio fields.

Mappings

The mappings transform the Ethereum data your mappings are sourcing into entities defined in your schema. Mappings are written in a subset of TypeScript called AssemblyScript.

Event Handlers

For each event handler that is defined in subgraph.yaml under mapping.eventHandlers, create an exported function of the same name. Each handler must accept a single parameter called event with a type corresponding to the name of the event which is being handled.

Event Handler part in the subgraph.yaml above:

Event Handlers

An example of Event Handlers mapping code:

Event Handler Mapping Code

This is the handler code which processes the events defined in the subgraph.yaml we gave above.

Call Handlers

While events provide an effective way to collect relevant changes to the state of a contract, many contracts avoid generating logs to optimize gas costs. In these cases, a subgraph can subscribe to calls made to the data source contract. This is achieved by defining call handlers referencing the function signature and the mapping handler that will process calls to this function. To process these calls, the mapping handler will receive an ethereum.Call as an argument with the typed inputs to and outputs from the call. Calls made at any depth in a transaction’s call chain will trigger the mapping, allowing activity with the data source contract through proxy contracts to be captured.

Call Handler part in the subgraph.yaml above:

Call Handler

An example of Call Handlers mapping code:

Call Handler Mapping Code

Block Handlers

In addition to subscribing to contract events or function calls, a subgraph may want to update its data as new blocks are appended to the chain. To achieve this a subgraph can run a function after every block or after blocks that match a predefined filter.

Block Handler part in the subgraph.yaml above:

Block Handler

An example of Block Handlers mapping code:

Block Handler Mapping Code

The defined handler will be called once for every block which contains a call to the contract (data source) the handler is defined under.The absense of a filter for a block handler will ensure that the handler is called every block.

Conclusions

This document has simplified the papers supplied by TheGraph official team, which in my opinion, are a little bit complex for new beginner. It gave an introduction of subgraph. With this document, I hope sincerely it would help those who are struggling and TheGraph would be better~

Official docs: https://thegraph.com/docs/define-a-subgraph#defining-fulltext-search-fields

--

--