Subgraph Manifest
1. What is subgraph.yaml
?
The subgraph.yaml file or the subgraph manifest is a YAML config file which is used to define the blockchain, the smart contracts to index, the events to listen to, and how to map the blockchain data to the entities defined in your schema.
2. How to define the manifest?
This is what the average subgraph.yaml
file looks like:
specVersion: 0.0.4
description: Gravatar for Ethereum
repository: https://github.com/graphprotocol/graph-tooling
schema:
file: ./schema.graphql
indexerHints:
prune: auto
dataSources:
- kind: ethereum/contract
name: Gravity
network: mainnet
source:
address: '0x2E645469f354BB4F5c8a05B3b30A929361cf77eC'
abi: Gravity
startBlock: 6175244
endBlock: 7175245
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
callHandlers:
- function: createGravatar(string,string)
handler: handleCreateGravatar
blockHandlers:
- handler: handleBlock
- handler: handleBlockWithCall
filter:
kind: call
file: ./src/mapping.ts
- kind: ethereum/contract
name: Factory
network: mainnet
source:
address: '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95'
abi: Factory
mapping:
kind: ethereum/events
apiVersion: 0.0.6
language: wasm/assemblyscript
entities:
- Directory
abis:
- name: Factory
file: ./abis/factory.json
eventHandlers:
- event: NewExchange(address,address)
handler: handleNewExchange
file: ./src/mappings/factory.ts
templates:
- name: Exchange
kind: ethereum/contract
network: mainnet
source:
abi: Exchange
mapping:
kind: ethereum/events
apiVersion: 0.0.6
language: wasm/assemblyscript
file: ./src/mappings/exchange.ts
entities:
- Exchange
abis:
- name: Exchange
file: ./abis/exchange.json
eventHandlers:
- event: TokenPurchase(address,uint256,uint256)
handler: handleTokenPurchase
- event: EthPurchase(address,uint256,uint256)
handler: handleEthPurchase
- event: AddLiquidity(address,uint256,uint256)
handler: handleAddLiquidity
- event: RemoveLiquidity(address,uint256,uint256)
handler: handleRemoveLiquidity
We won’t fall into details about each property, you can check the official TheGraph docs what every property means here. But we will touch on the most important details.
dataSources
dataSources
represent the contracts which we want to index. Here we define the contract address, the contract ABI, from which block to start to index the contract, which events, function we are interested in, on which chain the contract is deployed, etc. You can index multiple contracts within a single subgraph, by specifying multiple dataSources
-
network
- this property specifies on which chain the contract is deployed, for examplemainnet
,goerli
,matic
,mumbai
, etc. Full list of supported chains can be found here. Keep in mind that although you can specify anetwork
for each dataSource, all contracts must be on the same chain. Currently subgraphs don’t support specifying different chains for different dataSources. -
source.address
- This is an optional property, that specifies the contract address we want to index. If omitted, the subgraph will index every contract that matches the specified contract ABI. Omitting the address may be useful in some cases, for example there are multiple subgraph that index all ERC20 or ERC721 transfers. But keep in mind, there could be events from other contracts that match or fake the events that you are interested in, so you have to be careful and to make the proper checks in your mappings code. Or, as in the ERC20 and ERC721 case, theTransfer
event emitted by both standards have the same signature, and the only way to know which is which is to get the number of topics they have. More about this is explained later in the Handlers section. -
source.startBlock
- optional property, it indicates from which block the subgraph will start indexing the dataSource, usually the contract deployment block. Although optional it is advised to set the startBlock if you’re indexing a specific contract (i.e. you have set an contract address), otherwise the subgraph will start indexing from the genesis block and may take some time to sync. -
source.endBlock
- optional property, indicates the block after which the subgraph will stop indexing the contract. This is helpful when newer updated version of some contracts are deployed and the older ones are not used anymore. -
mapping.entities
- required property, the entities defined in theschema.graphql
file, that the dataSource writes to the store. -
mapping.abis
- required property, defines the contract ABI, and any additional contract ABIs that the subgraph may interact with, for example by View Function Calls.For example, an event emits and address of a contract and you want to call a function to access the contract state, you will need to have that contract ABI, add the path to the
abis
list, and graph-cli will generate the proper helpers, so you can do that from the mappings. -
mapping.eventHandlers
- A list of event signatures and the name of the functions in your mappings that will be used to map the blockchain data to the entities. More oneventHandlers
can be found here. -
mapping.callHandlers
- A list of function signatures and the name of the functions in your mapping that will be used to map the blockchain data to the entities. More oncallHandlers
can be found here. -
mapping.blockHandlers
- A list of functions which will be triggered on different occasions, depending if and whatfilter
is specified. Available filters arecall
,once
,every
. More onblockHandlers
can be found here. -
mapping.file
- the path to the file containing the handler functions, written in AssemblyScript.
Templates
There are two types of templates - contract templates (ethereum/contract
) and file data source templates(file/ipfs
or file/arweave
)
ethereum/contract
- The use of registry or factory contracts is a common pattern in EVM-based contracts. These contracts are used to create or manages a number of other sub/child contracts. The addresses of the sub/child contracts can’t always be know upfront and new contracts can be added with time. AddingdataSources
for those contracts may not always be possible, or may require manually doing it, redeploying the subgraph, waiting for the subgraph to sync, etc. In this case a more dynamic approach is required. This is wheretemplates
ordynamic dataSources
come forth. First you define a normaldataSource
for the factory/registry contract, which will usually emit an event containing the address of the newly created or registered contract and optionally any other information, like constructor params, etc. Then you add a template[s] for each type ofchild
orsubcontract
created or managed by thefactory
/registry
contract. The main difference between the regulardataSources
an thetemplates
is that templates are missing theaddress
andstartBlock
properties. The address is specified when the dataSource is initialised in the event handler of themain
/parent
contract, and thestartBlock
is automatically assigned to the block in which the event has been emitted. More on how to define and instantiate dynamicdataSources
can be found in the TheGraph documentation.file/ipfs
- Also calledFile Data Sources
, this is a functionality for accessing off-chain data during indexing and aims to replace the IPFS API. The Graph documentation has a comprehensive guide on how to declare and use file data sources, which can be found here. Also you can check this great tutorial on file data sources