Reemplazar un contrato y mantener su historia con el grafting
Reading time: 6 minutes
En esta guía, aprenderás a construir y deployar nuevos subgrafos mediante grafting (injerto) de subgrafos existentes.
¿Qué es el Grafting?
El grafting reutiliza los datos de un subgrafo existente y comienza a indexarlo en un bloque posterior. Esto es útil durante el desarrollo para superar rápidamente errores simples en los mapeos o para hacer funcionar temporalmente un subgrafo existente después de que haya fallado. También se puede utilizar cuando se añade un feature a un subgrafo que tarda en indexarse desde cero.
El subgrafo grafteado puede utilizar un esquema GraphQL que no es idéntico al del subgrafo base, sino simplemente compatible con él. Tiene que ser un esquema de subgrafo válido por sí mismo, pero puede diferir del esquema del subgrafo base de las siguientes maneras:
- Agrega o elimina tipos de entidades
- Elimina los atributos de los tipos de entidad
- Agrega atributos anulables a los tipos de entidad
- Convierte los atributos no anulables en atributos anulables
- Añade valores a los enums
- Agrega o elimina interfaces
- Cambia para qué tipos de entidades se implementa una interfaz
Para más información, puedes consultar:
In this tutorial, we will be covering a basic use case. We will replace an existing contract with an identical contract (with a new address, but the same code). Then, graft the existing subgraph onto the “base” subgraph that tracks the new contract.
Important Note on Grafting When Upgrading to the Network
Caution: It is recommended to not use grafting for subgraphs published to The Graph Network
Why Is This Important?
Grafting is a powerful feature that allows you to “graft” one subgraph onto another, effectively transferring historical data from the existing subgraph to a new version. It is not possible to graft a subgraph from The Graph Network back to Subgraph Studio.
Best Practices
Initial Migration: when you first deploy your subgraph to the decentralized network, do so without grafting. Ensure that the subgraph is stable and functioning as expected.
Subsequent Updates: once your subgraph is live and stable on the decentralized network, you may use grafting for future versions to make the transition smoother and to preserve historical data.
By adhering to these guidelines, you minimize risks and ensure a smoother migration process.
Construcción de un subgrafo existente
Building subgraphs is an essential part of The Graph, described more in depth here. To be able to build and deploy the existing subgraph used in this tutorial, the following repo is provided:
Note: The contract used in the subgraph was taken from the following Hackathon Starterkit.
Definición de manifiesto del subgrafo
The subgraph manifest subgraph.yaml
identifies the data sources for the subgraph, the triggers of interest, and the functions that should be run in response to those triggers. See below for an example subgraph manifest that you will use:
specVersion: 0.0.4schema: file: ./schema.graphqldataSources: - kind: ethereum name: Lock network: sepolia source: address: '0xb3aabe721794b85fe4e72134795c2f93b4eb7e63' abi: Lock startBlock: 5955690 mapping: kind: ethereum/events apiVersion: 0.0.6 language: wasm/assemblyscript entities: - Withdrawal abis: - name: Lock file: ./abis/Lock.json eventHandlers: - event: Withdrawal(uint256,uint256) handler: handleWithdrawal file: ./src/lock.ts
- The
Lock
data source is the abi and contract address we will get when we compile and deploy the contract - The network should correspond to an indexed network being queried. Since we’re running on Sepolia testnet, the network is
sepolia
- The
mapping
section defines the triggers of interest and the functions that should be run in response to those triggers. In this case, we are listening for theWithdrawal
event and calling thehandleWithdrawal
function when it is emitted.
Definición del manifiesto de grafting
El grafting requiere añadir dos nuevos items al manifiesto original del subgrafo:
---features: - grafting # feature namegraft: base: Qm... # subgraph ID of base subgraph block: 5956000 # block number
features:
is a list of all used feature names.graft:
is a map of thebase
subgraph and the block to graft on to. Theblock
is the block number to start indexing from. The Graph will copy the data of the base subgraph up to and including the given block and then continue indexing the new subgraph from that block on.
The base
and block
values can be found by deploying two subgraphs: one for the base indexing and one with grafting
Deploy del subgrafo base
- Go to Subgraph Studio and create a subgraph on Sepolia testnet called
graft-example
- Follow the directions in the
AUTH & DEPLOY
section on your subgraph page in thegraft-example
folder from the repo - Una vez que hayas terminado, verifica que el subgrafo se está indexando correctamente. Si ejecutas el siguiente comando en The Graph Playground
{ withdrawals(first: 5) { id amount when }}
Devuelve algo como esto:
{ "data": { "withdrawals": [ { "id": "0xe8323d21c4f104607b10b0fff9fc24b9612b9488795dea8196b2d5f980d3dc1d0a000000", "amount": "0", "when": "1716394824" }, { "id": "0xea1cee35036f2cacb72f2a336be3e54ab911f5bebd58f23400ebb8ecc5cfc45203000000", "amount": "0", "when": "1716394848" } ] }}
Una vez que hayas verificado que el subgrafo se está indexando correctamente, puedes actualizar rápidamente el subgrafo con grafting.
Deploy del subgrafo grafting
El subgraph.yaml de sustitución del graft tendrá una nueva dirección de contrato. Esto podría ocurrir cuando actualices tu dApp, vuelvas a deployar un contrato, etc.
- Go to Subgraph Studio and create a subgraph on Sepolia testnet called
graft-replacement
- Create a new manifest. The
subgraph.yaml
forgraph-replacement
contains a different contract address and new information about how it should graft. These are theblock
of the last event emitted you care about by the old contract and thebase
of the old subgraph. Thebase
subgraph ID is theDeployment ID
of your originalgraph-example
subgraph. You can find this in Subgraph Studio. - Follow the directions in the
AUTH & DEPLOY
section on your subgraph page in thegraft-replacement
folder from the repo - Una vez que hayas terminado, verifica que el subgrafo se está indexando correctamente. Si ejecutas el siguiente comando en The Graph Playground
{ withdrawals(first: 5) { id amount when }}
Debería devolver lo siguiente:
{ "data": { "withdrawals": [ { "id": "0xe8323d21c4f104607b10b0fff9fc24b9612b9488795dea8196b2d5f980d3dc1d0a000000", "amount": "0", "when": "1716394824" }, { "id": "0xea1cee35036f2cacb72f2a336be3e54ab911f5bebd58f23400ebb8ecc5cfc45203000000", "amount": "0", "when": "1716394848" }, { "id": "0x2410475f76a44754bae66d293d14eac34f98ec03a3689cbbb56a716d20b209af06000000", "amount": "0", "when": "1716429732" } ] }}
You can see that the graft-replacement
subgraph is indexing from older graph-example
data and newer data from the new contract address. The original contract emitted two Withdrawal
events, Event 1 and Event 2. The new contract emitted one Withdrawal
after, Event 3. The two previously indexed transactions (Event 1 and 2) and the new transaction (Event 3) were combined together in the graft-replacement
subgraph.
Congrats! You have successfully grafted a subgraph onto another subgraph.
Recursos Adicionales
If you want more experience with grafting, here are a few examples for popular contracts:
To become even more of a Graph expert, consider learning about other ways to handle changes in underlying datasources. Alternatives like Data Source Templates can achieve similar results
Note: A lot of material from this article was taken from the previously published Arweave article