OpenZeppelin recently released OpenZeppelin Subgraphs, a set of modules and CLI tools that make it easy to index OpenZeppelin contracts activity and make it available via an open API using The Graph Protocol.
These tools abstract away a lot of the code that you'd typically need to write to create a Subgraph when using various modules that OpenZeppelin supports.
As of now, the project supports these modules:
- AccessControl
- ERC20
- ERC721
- ERC1155
- ERC1967Upgrade
- Governor
- Ownable
- Pausable
- Timelock
Using the project, you can get up and running with a subgraph in just a few minutes, either deploying it as is, or using it as a boilerplate and adding your own customizations.
In this guide, we'll look at how to leverage OpenZeppelin Subgraphs to build an NFT API that indexes and makes data queryable from a few NFT smart contracts - Cool Cats and Pudgy Penguins.
The API will allow us to query NFT data from these two projects, making both the NFT data as well as the data from the acounts that own the NFTs available.
Here are the smart contract addresses that we'll be working with:
To be successful in this guide, you will need the following
- Node.js - Consider nvm to install Node.js on your machine
- Graph CLI
- Metamask or WalletConnect compatible wallet
To get started, we'll first need to initialize a new subgraph in the Subgraph Studio.
Go to https://thegraph.com/studio/ and click Connect Wallet to connect your Ethereum wallet.
Next, click Create a Subgraph to create a new subgraph.
Here, give the subgraph a name (like FunNFTs) and click Continue.
Now the subgraph has been initialized in the Subgraph Studio and we can continue to our local development environment.
Next, we'll create a new folder and initialize a new package.json
file:
npm init --y
Next, install the OpenZeppelin Subgraph package:
npm install @openzeppelin/subgraphs
Now all we need to do is define the smart contract addresses as well as the entity types that we'd like to index.
To do so, we can create a new file named subgraphconfig.json and add the following lines of configuration:
{
"output": "generated/",
"chain": "mainnet",
"datasources": [
{ "address": "0xBd3531dA5CF5857e7CfAA92426877b022e612cf8", "startBlock": 12878203, "module": [ "erc721", "ownable" ] },
{ "address": "0x1a92f7381b9f03921564a437210bb9396471050c", "startBlock": 12743024, "module": [ "erc721", "ownable" ] }
]
}
The array of data sources allows us to define the following properties for each item in the array:
- Smart contract address
- The start block (optional)
- Array of entities / modules that we'd like to index.
In the coonfiguration we've created, we've decided to index both the erc721
token data as well as ownable
for indexing the ownership information of the tokens.
That is all of the configuration we need! We can now build the subgraph.
To build the subgraph, run the following command:
npx graph-compiler \
--config subgraphconfig.json \
--include node_modules/@openzeppelin/subgraphs/src/datasources \
--export-schema \
--export-subgraph
After running this command, you should have the subgraph compiled in a new folder named generated. In this folder, you should see two files:
- schema.graphql - The GraphQL schema / data model
- subgraph.yaml - The main subgraph configuration
Now we are ready to deploy.
To deploy to Subgraph Studio and begin testing out the API, we need to have the subgraoh DEPLOY KEY as well as the SUBGRAPH SLUG, both of which are available in the Subgraph Studio dashboard for the individual subgraph.
First, change into the newly created generated folder:
cd generated
Next, we'll use the Graph CLI to authenticate and authorize the deployment from your local environment:
graph auth --studio
> Paste in DEPLOY KEY when prompted
Now, we can deploy by running the following command:
graph deploy --studio <subgrpahslug>
Once the deployment is complete, you should be ready to start testing it out!
In the Subgraph Studio you can run queries using the built in GraphQL Playground.
The first query we'll run will be to just return the NFT token data:
{
erc721Tokens {
id
identifier
uri
}
}
We can also enhance this query by passing in arguments, for instance if we wanted to order by the token identifier
:
{
erc721Tokens(
orderBy: identifier,
orderDirection: asc
) {
id
identifier
uri
}
}
We can query for transfer events, in the order in which they were transferred:
{
erc721Transfers(
orderBy: timestamp
orderDirection: desc
) {
timestamp
token {
identifier
uri
}
}
}
Finally, we may want to query for users and their tokens:
{
accounts {
id
ERC721tokens {
identifier
uri
}
}
}
The API is now ready to deploy. You can test it out in your front end application by following this guide, using the TEMPORARY QUERY URL given to you by the Subgraph Studio in the Details view.
When you are ready to put your API into production, you can publish your subgraph to the decentrlized network.
To learn how to build a subgraph from scratch, have a look at this guide.