Tiempo estimado: 6 minutos de lectura

Cómo probar, depurar e integrar un subgrafo de The Graph dentro de una DApp. Se describe el uso del playground para consultas GraphQL, la herramienta graph-client y estrategias avanzadas como autopaginación y recuperación de datos off-chain.

En qué consisten las pruebas e integración de un subgrafo en una DApp

En mi anterior artículo sobre el indexado de datos de la blockchain comencé a explorar la creación y despliegue de un subgrafo con The Graph.

Las pruebas e integración de un subgrafo en una DApp sería el siguiente paso natural del proceso: consiste en validar las entidades y los mapeos del subgrafo como prerrequisito para integrar el endpoint del subgrafo en la DApp que consumirá los datos disponibles.

Pruebas del subgrafo

Una vez tenemos desplegado e indexado el subgrafo en Subgraph Studio, el entorno de pruebas en The Graph, podemos ejecutar las primeras consultas de forma muy sencilla a través del "playground".

Se trata de un entorno accesible desde el panel de control que permite fácilmente componer consultas en GraphQL para extraer en vivo datos del subgrafo.

GraphQL es un estándar de lenguaje y un entorno de ejecución de lado servidor para permitir a clientes (APIs) la obtención de conjuntos de datos complejos a través de un único endpoint.

En la siguiente imagen se aprecia un ejemplo de uso del playground:

Graph Studio playground

Se ilustra la utilización del GraphiQL explorer, una interfaz que permite componer la consulta del cliente a partir de la selección de los elementos disponibles.

La consulta generada se puede utilizar directamente en los archivos de código fuente de la DApp para integrar el acceso a esos mismos datos.

Otra herramienta útil para probar y depurar un subgrafo sería el uso del logging API dentro del AssemblyScript API en The Graph. Permite registrar información de log dentro de los archivos de mapeo del subgrafo, usando varios niveles, para poder visualizarla desde Subgraph Studio o desde Graph Explorer.

Se ilustra con el siguiente fragmento de código


import { log } from "@graphprotocol/graph-ts";

const transferNumber = event.params.transferNumber;    
const idBytes = bigIntTo32Bytes(transferNumber);

log.info('Adding new ChildTransfer event for ID: {} {}', [transferNumber.toString(), idBytes.toHexString()]);

let entity = new ChildTransfer(idBytes);

Integración del subgrafo en la DApp

Una vez se ha probado y depurado el subgrafo, se podría integrar el consumo de los datos indexados desde la DApp.

Con The Graph existen varias alternativas. Por su versatilidad y sencillez, se recoge a continuación el uso del graph-client, el cliente propio desarrollado en el proyecto The Graph. Existen sin embargo otras opciones como Apollo Client o URQL también fácilmente integrables.

El primer paso consiste en instalar la CLI del cliente como dependencia de desarrollo, para posteriormente generar los archivos necesarios de producción:


yarn add -D @graphprotocol/client-cli 

Se debe crear un fichero ".graphclientrc.yml" en que se declare la URL del endpoint de desarrollo del subgrafo (se puede conseguir a través del portal en Subgraph Studio):


sources:
  - name: my-subgraph
    handler:
      graphql:
        endpoint: https://api.studio.thegraph.com/query/... 
        retry: 1
        timeout: 5000
    transforms:
      - autoPagination:
          validateSchema: false
          limitOfRecords: 1000

A partir de aquí se invoca la CLI para crear de forma automática los artefactos que permitan interactuar con el subgrafo desde la DApp:


yarn graphclient build 

Se crea la estructura de artefactos en el directorio ".graphclient".

Es importante reseñar que cada vez que se altere alguna configuración en el fichero ".graphclientrc.yml", se deben regenerar los artefactos.

Para consumir desde la DApp datos del subgrafo hay que importar la función "execute": método asíncrono que permite ejecutar consultas GraphQL suministrando los parámetros adecuados:


import { execute } from '.graphclient/index.js';
import { gql } from 'graphql-request'

const childTransferQuery = gql` 
  query MyQuery($parent: Bytes, $parentId: BigInt) {
    childTransfers(where: {parent: $parent, parentId: $parentId}
                  orderBy: id,
                  orderDirection: desc
                  first: 3000) 
    {    
      id    
      status    
      timestamp
      tokenId
    }
  } 
`

let childTransfer = await execute(childTransferQuery,
    {
      parent: parent,
      parentId: `${parentId}`
    }
  );

Opciones avanzadas del lado cliente

El cliente "graph-client" presenta algunas ventajas inherentes a su implementación. En general se configuran en el fichero ".graphclientrc.yml" (se pueden ver ejemplos en el suministrado como ejemplo anteriormente). Se destacan las dos siguientes:

  • Estrategias de recuperación: se pueden definir los reintentos máximos en caso de error, el tiempo máximo de espera y el uso de varios endpoints en modo redundante.
  • Autopaginación: el número máximo de resultados a recuperar en una consulta está limitado en The Graph a 1000. Para solventarlo se pueden paginar manualmente los resultados mediante "first/skip" o algún filtro (cursor filtering) o usar la función de autopaginación que lo gestiona de forma automática. Es importante reseñar que a pesar de todo, existe un límite máximo de 5000 resultados en una consulta autopaginada, teniendo que recurrir a paginación manual mediante filtrado si son necesarios más valores de retorno.

Indexado de datos off-chain

Otra de las utilidades que presenta un indexador es la posibilidad de mezclar datos generados fuera de la cadena (off-chain). The Graph en sus últimas actualizaciones provee el mecanismo de las fuentes de datos para acceder a datos off-chain de forma asíncrona, sin afectar el ritmo normal de indexación de los datos de la cadena.

Una de las fuentes de datos más habituales es IPFS, para cubrir entre otros el caso de uso típico de indexar cada NFT con sus metadatos.

Se esquematizan a continuación las definiciones básicas para este caso de uso:


#schema.graphql file
type ChildTransfer @entity(immutable: true) {
  id: Bytes!  
  metaData: IpfsMetadata # 0 or 1 IpfsMetadata
  tokenId: BigInt! # uint256  
  timestamp: BigInt! # uint256
  status: BigInt! # uint256 
}

type IpfsMetadata @entity(immutable: true) {
  id: Bytes!   
  metaData: String!
}


#subgraph.yaml
templates:
  - name: IpfsMetadata
    kind: file/ipfs
    mapping:      
      apiVersion: 0.0.9
      language: wasm/assemblyscript
      entities:
        - IpfsMetadata
      abis:
        - name: MembershipManager
          file: ./abis/MembershipManager.json
      handler: handleIpfsContent
      file: ./src/membership-manager.ts

      
# event handler in mappings file
// If the baseURI starts with "ipfs://", fetch metadata from IPFS
if(entity.baseURI.startsWith("ipfs://"))  {
    // Extract the CID from the baseURI
    let hash = entity.baseURI.substring(7, entity.baseURI.length);
    // Link the IpfsMetadata entity 
    entity.metaData = Bytes.fromUTF8(hash);
    
    // Create a new dynamic data source for the IpfsMetadata template
    IpfsMetadataTemplate.create(hash);
}

# file datasource handler in mapping file
export function handleIpfsContent(content: Bytes): void {
  
  let hash = dataSource.stringParam();
  log.warning('Handle metadata from: {}', [hash]);
  
  // link the on-chain data with the off-chain retrieved content
  let ipfs = new IpfsMetadata(Bytes.fromUTF8(hash));
  ipfs.metaData = content.toString();  
  ipfs.save();    
}

Conclusión: accediendo a datos estructurados de la blockchain desde las DApps

El consumo de datos estructurados de la blockchain desde una DApp es una tarea asequible y asumible mediante el uso de indexadores.

En este artículo se han presentado algunas claves que permiten poner a punto un subgrafo desplegado en The Graph mediante la herramienta Graph Studio.

Posteriormente el acceso a esos datos desde una aplicación descentralizada se puede conseguir mediante algunas de las librerías cliente disponibles para los desarrolladores.

La librería propia del proyecto The Graph se posiciona como una de las más versátiles y sencillas de utilizar, con algunas funciones avanzadas como la autopaginación para recuperar conjuntos amplios de resultados.

En el próximo artículo finalizaré el análisis de la plataforma The Graph tratando aspectos como las buenas prácticas en la construcción del subgrafo y su paso a producción en la red descentralizada.

¿Has utilizado alguna de las funciones avanzadas en The Graph para indexar los datos de tus smart contracts? ¿Mezclas datos de la cadena con información off-chain? ¡Comparte tus experiencias!


Si necesitas consumir datos estructurados desde tu DApp y no sabes cómo conseguir la información, puedo ayudarte a integrar un subgrafo en tu proyecto. Contáctame y analizamos juntos tu caso. ¡Un saludo!