Utilisez GraphQL pour développer un sous-graphe

Redallica
5 min readNov 13, 2020

Un sous-graphe (‘The Graph’) définit les données que le graphe indexera à partir d’Ethereum et comment il les stockera. Une fois déployé, il fera partie du graphe global de données blockchain.

La définition du sous-graphe se compose de quelques fichiers:

  • subgraph.yaml: un fichier YAML contenant le manifeste du sous - graphe
  • schema.graphql: un schéma GraphQL qui définit quelles données sont stockées pour votre sous-graphe, et comment l'interroger via GraphQL
  • AssemblyScript Mappings: Code AssemblyScript qui traduit les données d'événement dans Ethereum vers les entités définies dans votre schéma (par exemple mapping.tsdans ce tutoriel)

Le manifeste du sous-graphe

Le manifeste de sous-graphe subgraph.yamldéfinit les contrats intelligents de vos index de sous-graphe, les événements de ces contrats auxquels prêter attention et comment mapper les données d'événement aux entités que le node du graphe stocke et permet d'interroger. La spécification complète des manifestes de sous-graphes peut être trouvée ici .

Pour l’exemple de sous-graphe, subgraph.yamlest:

Exemple de manifeste d’un sous-graphe

Les entrées importantes à mettre à jour pour le manifeste sont:

  • description: une description lisible par l'homme de ce qu'est le sous-graphe. Cette description est affichée par l'explorateur de graphes lorsque le sous-graphe est déployé sur le service hébergé .
  • repository: l'URL du référentiel où le manifeste de sous-graphe peut être trouvé. Ceci est également affiché par l'explorateur de graphiques.
  • dataSources.source: le addressdu contrat intelligent, les sources du sous-graphe et le abicontrat intelligent à utiliser. Le addressest facultatif; l'omettre permet d'indexer les événements correspondants de tous les contrats.
  • dataSources.source.startBlock: le numéro facultatif du bloc à partir duquel la source de données commence l'indexation. Dans la plupart des cas, nous suggérons d'utiliser le bloc dans lequel le contrat a été créé.
  • dataSources.mapping.entities: les entités que la source de données écrit dans le magasin. Le schéma de chaque entité est défini dans le fichierschema.graphql.
  • dataSources.mapping.abis: un ou plusieurs fichiers ABI nommés pour le contrat source ainsi que tous les autres contrats intelligents avec lesquels vous interagissez à partir des mappages.
  • dataSources.mapping.eventHandlers: répertorie les événements de contrat intelligent auxquels ce sous-graphe réagit et les gestionnaires du mappage - ./src/mapping.tsdans l'exemple - qui transforment ces événements en entités dans le magasin.
  • dataSources.mapping.callHandlers: répertorie les fonctions de contrat intelligent auxquelles ce sous-graphique réagit et les gestionnaires du mappage qui transforment les entrées et les sorties en appels de fonction en entités dans le magasin.
  • dataSources.mapping.blockHandlers: répertorie les blocs auxquels ce sous-graphe réagit et les gestionnaires du mappage à exécuter lorsqu'un bloc est ajouté à la chaîne. Sans filtre, le gestionnaire de blocs sera exécuté à chaque bloc. Un filtre optionnel peut être fourni avec les types suivants: call. Un filtre callexécutera le gestionnaire si le bloc contient au moins un appel au contrat de source de données.

Un seul sous-graphe peut indexer les données de plusieurs contrats intelligents. Ajoutez une entrée pour chaque contrat à partir de laquelle les données doivent être indexées dans le tableau dataSources.

Les déclencheurs d’une source de données dans un bloc sont classés à l’aide du processus suivant:

  1. Les déclencheurs d’événement et d’appel sont d’abord classés par index de transaction dans le bloc.
  2. Les déclencheurs d’événement et d’appel dans la même transaction sont ordonnés selon une convention: les déclencheurs d’événement d’abord puis les déclencheurs d’appel, chaque type respectant l’ordre dans lequel ils sont définis dans le manifeste.
  3. Les déclencheurs de bloc sont exécutés après les déclencheurs d’événement et d’appel, dans l’ordre dans lequel ils sont définis dans le manifeste.

Ces règles de commande sont susceptibles d’être modifiées.

Le ou les fichiers ABI doivent correspondre à votre (vos) contrat (s). Il existe plusieurs façons d’obtenir des fichiers ABI:

  • Si vous créez votre propre projet, vous aurez probablement accès à vos ABI les plus récents.
  • Si vous créez un sous-graphe pour un projet public, vous pouvez télécharger ce projet sur votre ordinateur et obtenir l’ABI en utilisant truffle compile ou en utilisant solcpour compiler.
  • Vous pouvez également trouver l’ABI sur Etherscan , mais ce n’est pas toujours fiable, car l’ABI qui y est téléchargé peut être obsolète. Assurez-vous d’avoir le bon ABI, sinon l’exécution de votre sous-graphe échouera.

Le schéma GraphQL

Le schéma de votre sous-graphe se trouve dans le fichier schema.graphql. Les schémas GraphQL sont définis à l'aide du langage de définition d'interface GraphQL. Si vous n'avez jamais écrit de schéma GraphQL, il est recommandé de consulter cette introduction sur le système de types GraphQL. La documentation de référence pour les schémas GraphQL se trouve dans la section API GraphQL .

Définition d’entité

Avant de définir des entités, il est important de prendre du recul et de réfléchir à la manière dont vos données sont structurées et liées. Toutes les requêtes seront effectuées sur le modèle de données défini dans le schéma de sous-graphe et les entités indexées par le sous-graphe. Pour cette raison, il est bon de définir le schéma de sous-graphe d’une manière qui correspond aux besoins de votre dApp. Il peut être utile d’imaginer les entités comme des “objets contenant des données”, plutôt que comme des événements ou des fonctions.

Avec The Graph, vous définissez simplement les types d’entités dans schema.graphql, et Graph Node générera des champs de niveau supérieur pour interroger des instances uniques et des collections de ce type d'entité. Chaque type qui devrait être une entité doit être annoté avec une @entitydirective.

Le mapping

Le mapping transforme les données Ethereum en entités définies dans votre schéma. Les données mappées sont écrites dans un sous-ensemble de TypeScript appelé AssemblyScript qui peut être compilé en WASM ( WebAssembly ). AssemblyScript est plus strict que TypeScript normal, mais fournit une syntaxe familière.

Pour chaque gestionnaire d’événements défini dans subgraph.yaml sousmapping.eventHandlers, créez une fonction exportée du même nom. Chaque gestionnaire doit accepter un seul paramètre appelé eventavec un type correspondant au nom de l'événement qui est géré.

Dans l’exemple de sous-graphe, src/mapping.tscontient des gestionnaires pour les événements NewGravataret UpdatedGravatar:

Exemple de Mapping d’un sous-graphe

Le premier gestionnaire prend un NewGravatarévénement et crée une nouvelle Gravatar entité avec new Gravatar(event.params.id.toHex()), en remplissant les champs d'entité à l'aide des paramètres d'événement correspondants. Cette instance d'entité est représentée par la variable gravatar, avec une idvaleur de event.params.id.toHex().

Le second gestionnaire tente de charger l’existant à Gravatarpartir du magasin de nœud de graphique. S'il n'existe pas encore, il est créé à la demande. L'entité est ensuite mise à jour pour correspondre aux nouveaux paramètres d'événement, avant d'être sauvegardée dans le magasin à l'aide de gravatar.save().

--

--