Reemplazar un contrato y mantener su historia con el grafting
Reading time: 6 min
En esta guía, aprenderás a construir y deployar nuevos subgrafos mediante grafting (injerto) de subgrafos existentes.
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:
En este tutorial vamos a cubrir un caso de uso básico. Reemplazaremos un contrato existente con un contrato idéntico (con una nueva dirección, pero el mismo código). Luego, haremos grafting del subgrafo existente en el subgrafo "base" que rastrea el nuevo contrato.
Caution: It is recommended to not use grafting for subgraphs published to The Graph Network
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. While this is an effective way to preserve data and save time on indexing, grafting may introduce complexities and potential issues when migrating from a hosted environment to the decentralized network. It is not possible to graft a subgraph from The Graph Network back to the hosted service or Subgraph Studio.
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.
Building subgraphs is an essential part of The Graph, described more in depth . To be able to build and deploy the existing subgraph used in this tutorial, the following repo is provided:
El manifiesto del subgrafo subgraph.yaml
identifica las fuentes de datos para el subgrafo, los disparadores de interés y las funciones que deben ejecutarse en respuesta a esos disparadores. A continuación se muestra un ejemplo de manifiesto de subgrafos que se utilizará:
specVersion: 0.0.4schema:file: ./schema.graphqldataSources:- kind: ethereumname: Locknetwork: sepoliasource:address: '0xb3aabe721794b85fe4e72134795c2f93b4eb7e63'abi: LockstartBlock: 5955690mapping:kind: ethereum/eventsapiVersion: 0.0.6language: wasm/assemblyscriptentities:- Withdrawalabis:- name: Lockfile: ./abis/Lock.jsoneventHandlers:- event: Withdrawal(uint256,uint256)handler: handleWithdrawalfile: ./src/lock.ts
- La fuente de datos de
Lock
es el ABI y la dirección del contrato que obtendremos cuando compilemos y realicemos el deploy del contrato - The network should correspond to a indexed network being queried. Since we're running on Sepolia testnet, the network is
sepolia
- La sección de
mapeo
define los disparadores de interés y las funciones que deben ejecutarse en respuesta a esos disparadores. En este caso, estamos escuchando el eventoWithdrawal
y llamando a la funciónhandleWithdrawal
cuando se emite.
El grafting requiere añadir dos nuevos items al manifiesto original del subgrafo:
---features:- grafting # feature namegraft:base: Qm... # subgraph ID of base subgraphblock: 5956000 # block number
features:
is a list of all used .graft
: es un mapa del subgrafobase
y del bloque al que se va a realizar el grafting. Elbloque
es el número de bloque desde el que se empieza a indexar. The Graph copiará los datos del subgrafo base hasta el bloque dado, inclusive, y luego continuará indexando el nuevo subgrafo a partir de ese bloque.
Los valores de la base
y del bloque
se pueden encontrar deployando dos subgrafos: uno para la indexación de la base y otro con grafting
- Go to and create a subgraph on Sepolia testnet called
graft-example
- Sigue las instrucciones de la sección
AUTH & DEPLOY
en tu página de subgrafo en la carpetagraft-example
del 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) {idamountwhen}}
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.
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 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 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. - Sigue las instrucciones de la sección
AUTH & DEPLOY
en la página de tu subgrafo en la carpetagraft-replacement
del 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) {idamountwhen}}
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, and . The new contract emitted one Withdrawal
after, . 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.
Si quieres tener más experiencia con el grafting, aquí tienes algunos ejemplos de contratos populares:
To become even more of a Graph expert, consider learning about other ways to handle changes in underlying datasources. Alternatives like can achieve similar results