💻
Subgraph Development
This guide will walk you through the steps required to develop, build, and deploy a subgraph file.
We’ll start with a comprehensive description of The Graph technology, after which we’ll show you how to write and deploy a subgraph configuration.
Note: for this one, we’re also going to show you how you would index the Klayswap smart contract on the Klaytn network.
You can clone the fully functional demo from the Klaytn Indexing repo, along with all the required infrastructure configuration and examples
The Graph is an indexing protocol empowering applications to retrieve, aggregate in a stateful manner, then query data from a blockchain through a customizable and abstracted approach.
Before The Graph, dApps had to build their own data pipeline to fetch the history of targeted smart contracts, store the raw information and create specialized solutions to process it before serving their end users.
The EVM has a logging functionality used to “write” data outside smart contracts though emitting formatted logs called events. Events allow smart contracts to “print” information on the blockchain in a way that is more searchable and gas efficient than just saving it to their public storage.
These logs are associated with the address of the emitting contract, immutable once persisted into the blockchain and accessible at any time. The event logs are not accessible from within contracts (not even from the contract that created them). It is their inaccessibility to smart contracts that makes them cheaper to emit.
Emitting events enables the possibility to:
- Test smart contracts for conditions and invariants
- Reconstruct a contract`s state by indexing and aggregating past logs
- Listen for specific events to trigger an offchain operation
- Access large blockchain data faster and more structured than reading it directly from smart contracts
The definition of an event in the Solidity language looks like this:
event Transfer(address indexed from, address indexed to, uint256 value);
You can think of this as a new special type. We have created a “type” of event called
Transfer
. The event name is called and can hold a number of variables. There are two kinds of enclosed parameters: indexed and non-indexed. You can assign the attribute indexed
to up to three parameters which adds them to a special data structure known as topics
instead of the data part of the log. A topic can only hold a single word (32 bytes) so if you use a reference type for an indexed argument, the keccak256 hash of the value is stored as a topic instead. All parameters without the indexed attribute are ABI-encoded into the data part of the log.Topics enable filtered search of events at the granularity of indexed parameters. For example, can fetch only
Transfer
events in a blocks range between two specific wallets, from
and to
.Can emit an event within the defining contract as:
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
_balances[sender] -= amount;
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
}
Now, anytime we call the
_transfer
function in this example, it will emit an event of type Transfer
.Example of a
Transfer
log instance within a random transaction as displayed on the klaytn explorer:
Emitted logs are stored on the blockchain as:
- Address: the address of the contract or account that emitted the event.
- Topics: the values (or hashes) of the indexed parameters of the event, the first topic representing the hash of the signature of the event definition.
- Data: the ABI-encoded non-indexed parameters logged by this event instance.
The Graph facilitates the building of custom open APIs through “subgraphs”. A subgraph represents a packed configuration that instructs an indexer node (server) which data to index from a blockchain and how to aggregate it before storing the results structurally into a Postgres database. The indexer exposes each hosted subgraph through a GraphQL endpoint, allowing users to query the data it managed to process so far.
In order to install The Graph CLI,
npm
or yarn
should be installed either on your machine or on a VSCode development container extending the nodejs
docker image.Install with npm (possibly under
sudo
privileges):npm install -g @graphprotocol/graph-cli
Install with yarn (possibly under
sudo
privileges):yarn global add @graphprotocol/graph-cli
Additionally, there is the Graph Typescript Library which contains utilities for interacting with the entities store and conveniences for handling smart contract data:
npm install --dev @graphprotocol/graph-ts
or
yarn add --dev @graphprotocol/graph-ts
Once The Graph CLI has been installed, the
graph init
command can be used to set up a new subgraph project. For Klaytn (EVM-compatible chain) the protocol is ethereum
, the subgraph project will be created locally using the subgraph-studio
option, the published source code of the targeted contract is searched only on the Ethereum explorer, therefore the ABI of the contract should be manually supplied instead. The subgraph slug can be left blank as the subgraph is not meant to be run remotely on The Graph`s hosted service, not supporting Klaytn.graph init
On successfully running
graph init
the console should look similar to:graph init
✔ Protocol · ethereum
✔ Product for which to initialize · subgraph-studio
✔ Subgraph slug ·
✔ Directory to create the subgraph in · subgraph-demo
? Ethereum network …
✔ Ethereum network · mainnet