16 minutes
Manifeste de Subgraph
Aperçu
The Subgraph manifest, subgraph.yaml
, defines the smart contracts & network your Subgraph will index, the events from these contracts to pay attention to, and how to map event data to entities that Graph Node stores and allows to query.
The Subgraph definition consists of the following files:
-
subgraph.yaml
: Contains the Subgraph manifest -
schema.graphql
: A GraphQL schema defining the data stored for your Subgraph and how to query it via GraphQL -
mapping.ts
: Mappage AssemblyScript code qui traduit les données d’événements en entités définies dans votre schéma (par exemplemapping.ts
dans ce guide)
Capacités des subgraphs
Un seul Subgraph peut :
-
Indexer les données de plusieurs contrats intelligents (mais pas de plusieurs réseaux).
-
Indexer des données de fichiers IPFS en utilisant des File Data Sources.
-
Ajouter une entrée pour chaque contrat nécessitant une indexation dans le tableau
dataSources
.
La spécification complète des manifestes de Subgraphs est disponible ici.
Pour l’exemple de Subgraph cité ci-dessus, subgraph.yaml
est :
1specVersion: 1.3.02description: Gravatar for Ethereum3repository: https://github.com/graphprotocol/graph-tooling4schema:5 file: ./schema.graphql6indexerHints:7 prune: auto8dataSources:9 - kind: ethereum/contract10 name: Gravity11 network: mainnet12 source:13 address: '0x2E645469f354BB4F5c8a05B3b30A929361cf77eC'14 abi: Gravity15 startBlock: 617524416 endBlock: 717524517 context:18 foo:19 type: Bool20 data: true21 bar:22 type: String23 data: 'bar'24 mapping:25 kind: ethereum/events26 apiVersion: 0.0.927 language: wasm/assemblyscript28 entities:29 - Gravatar30 abis:31 - name: Gravity32 file: ./abis/Gravity.json33 eventHandlers:34 - event: NewGravatar(uint256,address,string,string)35 handler: handleNewGravatar36 - event: UpdatedGravatar(uint256,address,string,string)37 handler: handleUpdatedGravatar38 callHandlers:39 - function: createGravatar(string,string)40 handler: handleCreateGravatar41 blockHandlers:42 - handler: handleBlock43 - handler: handleBlockWithCall44 filter:45 kind: call46 file: ./src/mapping.ts
Entrées de subgraphs
Remarque importante : veillez à remplir votre manifeste de Subgraph avec tous les gestionnaires et entités.
Les entrées importantes à mettre à jour pour le manifeste sont :
-
specVersion
: une version du semver qui identifie la structure du manifeste et les fonctionnalités supportées pour le Subgraph. La dernière version est1.3.0
. Voir la section specVersion releases pour plus de détails sur les fonctionnalités et les releases. -
description
: une description lisible par l’homme de ce qu’est le Subgraph. Cette description est affichée dans Graph Explorer lorsque le Subgraph est déployé dans Subgraph Studio. -
repository
: l’URL du dépôt où le manifeste du Subgraph peut être trouvé. Cette URL est également affichée dans Graph Explorer. -
features
: une liste de tous les noms de fonctionnalités utilisés. -
indexerHints.prune
: Définit la conservation des données de blocs historiques pour un Subgraph. Voir élaguage dans la section indexerHints. -
dataSources.source
: l’adresse du contrat intelligent dont le Subgraph s’inspire, et l’ABI du contrat intelligent à utiliser. L’adresse est optionnelle ; l’omettre permet d’indexer les événements correspondants de tous les contrats. -
dataSources.source.startBlock
: le numéro optionnel 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.source.endBlock
: Le numéro optionnel du bloc sur lequel la source de données arrête l’indexation, y compris ce bloc. Version minimale de la spécification requise :0.0.9
. -
dataSources.context
: paires clé-valeur qui peuvent être utilisées dans les mappages de subgraphs. Supporte différents types de données commeBool
,String
,Int
,Int8
,BigDecimal
,Bytes
,List
, etBigInt
. Chaque variable doit spécifier sontype
et sesdonnées
. Ces variables de contexte sont ensuite accessibles dans les fichiers de mappage, offrant plus d’options configurables pour le développement de Subgraph. -
dataSources.mapping.entities
: les entités que la source de données écrit dans le store. Le schéma de chaque entité est défini dans le fichier schema.graphql. -
dataSources.mapping.abis
: un ou plusieurs fichiers ABI nommés pour le contrat source ainsi que pour tous les autres contrats intelligents avec lesquels vous interagissez à partir des mappages. -
dataSources.mapping.eventHandlers
: liste les événements du contrat intelligent auxquels ce Subgraph réagit et les gestionnaires dans le mappage - ./src/mapping.ts dans l’exemple - qui transforment ces événements en entités dans le store. -
dataSources.mapping.callHandlers
: liste les fonctions du contrat intelligent auxquelles ce Subgraph réagit et les handlers dans le mappage qui transforment les entrées et sorties des appels de fonction en entités dans le store. -
dataSources.mapping.blockHandlers
: liste les blocs auxquels ce subgraph réagit et les gestionnaires du mappage à exécuter lorsqu’un bloc est ajouté à la blockchain. Sans filtre, le gestionnaire de bloc sera exécuté à chaque bloc. Un filtre d’appel optionnel peut être fourni en ajoutant un champfilter
aveckind : call
au gestionnaire. Ceci ne lancera le gestionnaire que si le bloc contient au moins un appel au contrat de la source de données.
Un seul Subgraph peut indexer les données de plusieurs contrats intelligents. Ajoutez une entrée pour chaque contrat dont les données doivent être indexées dans le tableau dataSources
.
Gestionnaires d’événements
Les gestionnaires d’événements d’un Subgraph réagissent à des événements spécifiques émis par des contrats intelligents sur la blockchain et déclenchent des gestionnaires définis dans le manifeste du Subgraph. Cela permet aux Subgraphs de traiter et de stocker les données d’événements selon une logique définie.
Définition d’un gestionnaire d’événements
Un gestionnaire d’événements est déclaré dans une source de données dans la configuration YAML du Subgraph. Il spécifie les événements à écouter et la fonction correspondante à exécuter lorsque ces événements sont détectés.
1dataSources:2 - kind: ethereum/contract3 name: Gravity4 network: dev5 source:6 address: '0x731a10897d267e19b34503ad902d0a29173ba4b1'7 abi: Gravity8 mapping:9 kind: ethereum/events10 apiVersion: 0.0.911 language: wasm/assemblyscript12 entities:13 - Gravatar14 - Transaction15 abis:16 - name: Gravity17 file: ./abis/Gravity.json18 eventHandlers:19 - event: Approval(address,address,uint256)20 handler: handleApproval21 - event: Transfer(address,address,uint256)22 handler: handleTransfer23 topic1: ['0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', '0xc8dA6BF26964aF9D7eEd9e03E53415D37aA96325'] # Filtre thématique facultatif permettant de filtrer uniquement les événements ayant trait au thème spécifié.
Gestionnaires d’appels
Bien que les événements constituent un moyen efficace de collecter les modifications pertinentes de l’état d’un contrat, de nombreux contrats évitent de générer des logs afin d’optimiser les coûts de gaz. Dans ce cas, un subgraph peut s’abonner aux appels faits au contrat de source de données. Pour ce faire, il définit des gestionnaires d’appels référençant la signature de la fonction et le gestionnaire de mappage qui traitera les appels à cette fonction. Pour traiter ces appels, le gestionnaire de mappage recevra un ethereum.Call
comme argument avec les entrées et sorties typées de l’appel. Les appels effectués à n’importe quel niveau de la chaîne d’appel d’une transaction déclencheront le mappage, ce qui permettra de capturer l’activité avec le contrat de source de données par le biais de contrats proxy.
Les gestionnaires d’appels ne se déclencheront que dans l’un des deux cas suivants : lorsque la fonction spécifiée est appelée par un compte autre que le contrat lui-même ou lorsqu’elle est marquée comme externe dans Solidity et appelée dans le cadre d’une autre fonction du même contrat.
Note: Les gestionnaires d’appels dépendent actuellement de l’API de traçage de Parity. Certains réseaux, tels que BNB chain et Arbitrum, ne supportent pas cette API. Si un subgraph indexant l’un de ces réseaux contient un ou plusieurs gestionnaires d’appels, il ne commencera pas à se synchroniser. Les développeurs de subgraphs devraient plutôt utiliser des gestionnaires d’événements. Ceux-ci sont bien plus performants que les gestionnaires d’appels et sont pris en charge par tous les réseaux evm.
Définir un gestionnaire d’appels
Pour définir un gestionnaire d’appel dans votre manifeste, ajoutez simplement un tableau callHandlers
sous la source de données à laquelle vous souhaitez vous abonner.
1dataSources:2 - kind: ethereum/contract3 name: Gravity4 network: mainnet5 source:6 address: '0x731a10897d267e19b34503ad902d0a29173ba4b1'7 abi: Gravity8 mapping:9 kind: ethereum/events10 apiVersion: 0.0.911 language: wasm/assemblyscript12 entities:13 - Gravatar14 - Transaction15 abis:16 - name: Gravity17 file: ./abis/Gravity.json18 callHandlers:19 - function: createGravatar(string,string)20 handler: handleCreateGravatar
La propriété function
est la signature de la fonction normalisée pour filtrer les appels. La propriété handler
est le nom de la fonction dans votre mappage que vous souhaitez exécuter lorsque la fonction cible est appelée dans le contrat de la source de données.
Fonction de cartographie
Chaque gestionnaire d’appel prend un seul paramètre qui a un type correspondant au nom de la fonction appelée. Dans l’exemple du Subgraph ci-dessus, le mappage contient un gestionnaire pour l’appel de la fonction createGravatar
qui reçoit un paramètre CreateGravatarCall
comme argument :
1import { CreateGravatarCall } from '../generated/Gravity/Gravity'2import { Transaction } from '../generated/schema'34export function handleCreateGravatar(call: CreateGravatarCall): void {5 let id = call.transaction.hash6 let transaction = new Transaction(id)7 transaction.displayName = call.inputs._displayName8 transaction.imageUrl = call.inputs._imageUrl9 transaction.save()10}
La fonction handleCreateGravatar
prend un nouveau CreateGravatarCall
qui est une sous-classe de ethereum.Call
, fournie par @graphprotocol/graph-ts
, qui inclut les entrées et sorties typées de l’appel. Le type CreateGravatarCall
est généré pour vous lorsque vous lancez graph codegen
.
Block Handlers
Outre l’abonnement à des événements contractuels ou à des appels de fonction, un Subgraph peut vouloir mettre à jour ses données lorsque de nouveaux blocs sont ajoutés à la blockchain. Pour ce faire, un Subgraph peut exécuter une fonction après chaque bloc ou après les blocs qui correspondent à un filtre prédéfini.
Filtres pris en charge
Filtre d’appel
1filter:2 kind: call
Le gestionnaire défini sera appelé une fois pour chaque bloc qui contient un appel au contrat (source de données) sous lequel le gestionnaire est défini.
Note: Le filtre call
dépend actuellement de l’API de traçage de Parity. Certains réseaux, tels que BNB chain et Arbitrum, ne supportent pas cette API. Si un subgraph indexant un de ces réseaux contient un ou plusieurs block handlers avec un filtre call
, il ne commencera pas à se synchroniser.
L’absence de filtre pour un gestionnaire de bloc garantira que le gestionnaire est appelé à chaque bloc. Une source de données ne peut contenir qu’un seul gestionnaire de bloc pour chaque type de filtre.
1dataSources:2 - kind: ethereum/contract3 name: Gravity4 network: dev5 source:6 address: '0x731a10897d267e19b34503ad902d0a29173ba4b1'7 abi: Gravity8 mapping:9 kind: ethereum/events10 apiVersion: 0.0.911 language: wasm/assemblyscript12 entities:13 - Gravatar14 - Transaction15 abis:16 - name: Gravity17 file: ./abis/Gravity.json18 blockHandlers:19 - handler: handleBlock20 - handler: handleBlockWithCallToContract21 filter:22 kind: call
Filtre d’interrogation
Nécessite specVersion
>= 0.0.8
Note: Les filtres d’interrogation ne sont disponibles que sur les dataSources de kind : ethereum
.
1blockHandlers:2 - handler: handleBlock3 filter:4 kind: polling5 every: 10
Le gestionnaire défini sera appelé une fois tous les n
blocs, où n
est la valeur fournie dans le champ every
. Cette configuration permet au Subgraph d’effectuer des opérations spécifiques à intervalles réguliers.
Le filtre Once
Nécessite specVersion
>= 0.0.8
Note: Les filtres Once ne sont disponibles que sur les dataSources de kind : ethereum
.
1blockHandlers:2 - handler: handleOnce3 filter:4 kind: once
Le gestionnaire défini avec le filtre once ne sera appelé qu’une seule fois avant l’exécution de tous les autres gestionnaires. Cette configuration permet au Subgraph d’utiliser le gestionnaire comme gestionnaire d’initialisation, en exécutant des tâches spécifiques au début de l’indexation.
1export function handleOnce(block: ethereum.Block): void {2 let data = new InitialData(Bytes.fromUTF8('initial'))3 data.data = 'Setup data here'4 data.save()5}
Fonction de cartographie
La fonction de mappage recevra une ethereum.Block
comme seul argument. Comme les fonctions de mappage pour les événements, cette fonction peut accéder aux entités Subgraph existantes dans le store, appeler des contrats intelligents et créer ou mettre à jour des entités.
1import { ethereum } from '@graphprotocol/graph-ts'23export function handleBlock(block: ethereum.Block): void {4 let id = block.hash5 let entity = new Block(id)6 entity.save()7}
Événements anonymes
Si vous devez traiter des événements anonymes dans Solidity, cela peut être réalisé en fournissant le sujet 0 de l’événement, comme dans l’exemple :
1eventHandlers:2 - event: LogNote(bytes4,address,bytes32,bytes32,uint256,bytes)3 topic0: '0x644843f351d3fba4abcd60109eaff9f54bac8fb8ccf0bab941009c21df21cf31'4 handler: handleGive
Un événement ne sera déclenché que si la signature et le sujet 0 correspondent. Par défaut, topic0
est égal au hash de la signature de l’événement.
Reçus de transaction dans les gestionnaires d’événements
A partir de specVersion
0.0.5
et apiVersion
0.0.7
, les gestionnaires d’événements peuvent avoir accès au reçu de la transaction qui les a émis.
Pour ce faire, les gestionnaires d’événements doivent être déclarés dans le manifeste Subgraph avec la nouvelle clé receipt : true
, qui est facultative et prend par défaut la valeur false.
1eventHandlers:2 - event: NewGravatar(uint256,address,string,string)3 handler: handleNewGravatar4 receipt: true
Dans la fonction handler, le reçu peut être accédé dans le champ Event.receipt
. Si la clé receipt
est fixée à false
ou omise dans le manifeste, une valeur null
sera renvoyée à la place.
Ordre de déclenchement des gestionnaires
Les déclencheurs d’une source de données au sein d’un bloc sont classés à l’aide du processus suivant :
- Les déclencheurs d’événements et d’appels sont d’abord classés par index de transaction au sein du bloc.
- Les déclencheurs d’événements et d’appels au sein d’une même transaction sont classés selon une convention : les déclencheurs d’événements d’abord, puis les déclencheurs d’appel, chaque type respectant l’ordre dans lequel ils sont définis dans le manifeste.
- 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 de changer.
Note: Lorsque de nouvelles [sources de données dynamiques] (#data-source-templates-for-dynamically-created-contracts) sont créées, les gestionnaires définis pour les sources de données dynamiques ne commenceront à être traités qu’une fois que tous les gestionnaires de sources de données existants auront été traités, et se répéteront dans la même séquence chaque fois qu’ils seront déclenchés.
Modèles de sources de données
Un modèle courant dans les contrats intelligents compatibles EVM est l’utilisation de contrats de registre ou d’usine, dans lesquels un contrat crée, gère ou référence un nombre arbitraire d’autres contrats qui ont chacun leur propre état et leurs propres événements.
Les adresses de ces sous-contrats peuvent ou non être connues à l’avance et nombre de ces contrats peuvent être créés et/ou ajoutés au fil du temps. C’est pourquoi, dans de tels cas, la définition d’une source de données unique ou d’un nombre fixe de sources de données est impossible et une approche plus dynamique est nécessaire : les modèles de sources de données.
Source de données pour le contrat principal
Tout d’abord, vous devez définir une source de données régulière pour le contrat principal. L’extrait ci-dessous montre un exemple simplifié de source de données pour le contrat factory de l’exchange Uniswap. Notez le gestionnaire d’événement NewExchange(address,address)
. Il est émis lorsqu’un nouveau contrat d’exchange est créé onchain par le contrat factory.
1dataSources:2 - kind: ethereum/contract3 name: Factory4 network: mainnet5 source:6 address: '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95'7 abi: Factory8 mapping:9 kind: ethereum/events10 apiVersion: 0.0.911 language: wasm/assemblyscript12 file: ./src/mappings/factory.ts13 entities:14 - Directory15 abis:16 - name: Factory17 file: ./abis/factory.json18 eventHandlers:19 - event: NewExchange(address,address)20 handler: handleNewExchange
Modèles de source de données pour les contrats créés dynamiquement
Ensuite, vous ajoutez des modèles de sources de données au manifeste. Ceux-ci sont identiques aux sources de données classiques, sauf qu’ils n’ont pas d’adresse de contrat prédéfinie sous source
. Typiquement, vous devriez définir un modèle pour chaque type de sous-contrat géré ou référencé par le contrat parent.
1dataSources:2 - kind: ethereum/contract3 name: Factory4 # ... d'autres champs sources pour le contrat principal ...5templates:6 - name: Exchange7 kind: ethereum/contract8 network: mainnet9 source:10 abi: Exchange11 mapping:12 kind: ethereum/events13 apiVersion: 0.0.914 language: wasm/assemblyscript15 file: ./src/mappings/exchange.ts16 entities:17 - Exchange18 abis:19 - name: Exchange20 file: ./abis/exchange.json21 eventHandlers:22 - event: TokenPurchase(address,uint256,uint256)23 handler: handleTokenPurchase24 - event: EthPurchase(address,uint256,uint256)25 handler: handleEthPurchase26 - event: AddLiquidity(address,uint256,uint256)27 handler: handleAddLiquidity28 - event: RemoveLiquidity(address,uint256,uint256)29 handler: handleRemoveLiquidity
Instanciation d’un modèle de source de données
Dans la dernière étape, vous mettez à jour votre mappage du contrat principal pour créer une instance de source de données dynamique à partir de l’un des modèles. Dans cet exemple, vous modifiez le mappage du contrat principal pour importer le modèle Exchange
et appeler la méthode Exchange.create(address)
pour commencer à indexer le nouveau contrat d’exchange.
1import { Exchange } from '../generated/templates'23export function handleNewExchange(event: NewExchange): void {4 // Commence à indexer l'échange ; `event.params.exchange` est le5 // adresse du nouveau contrat d'échange6 Exchange.create(event.params.exchange)7}
Note: Une nouvelle source de données ne traitera que les appels et les événements du bloc dans lequel elle a été créée et de tous les blocs suivants, mais ne traitera pas les données historiques, c’est-à-dire les données contenues dans les blocs précédents.
Si les blocs précédents contiennent des données pertinentes pour la nouvelle source de données, il est préférable d’indexer ces données en lisant l’état actuel du contrat et en créant des entités représentant cet état au moment de la création de la nouvelle source de données.
Data Source Context
Les contextes de source de données permettent de passer une configuration supplémentaire lors de l’instanciation d’un modèle. Dans notre exemple, disons que les éxchanges sont associés à une paire de trading particulière, qui est incluse dans l’événement NewExchange
. Cette information peut être passée dans la source de données instanciée, comme suit :
1import { Exchange } from '../generated/templates'23export function handleNewExchange(event: NewExchange): void {4 let context = new DataSourceContext()5 context.setString('tradingPair', event.params.tradingPair)6 Exchange.createWithContext(event.params.exchange, context)7}
A l’intérieur d’un mappage du modèle Exchange
, il est possible d’accéder au contexte :
1import { dataSource } from '@graphprotocol/graph-ts'23let context = dataSource.context()4let tradingPair = context.getString('tradingPair')
Il existe des setters et getters comme setString
et getString
pour tous les types de valeurs.
Blocs de démarrage
Le startBlock
est un paramètre optionnel qui vous permet de définir à partir de quel bloc de la chaîne la source de données commencera l’indexation. La définition du bloc de départ permet à la source de données de sauter des millions de blocs potentiellement non pertinents. Typiquement, un développeur de Subgraph définira startBlock
au bloc dans lequel le contrat intelligent de la source de données a été créé.
1dataSources:2 - kind: ethereum/contract3 name: ExampleSource4 network: mainnet5 source:6 address: '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95'7 abi: ExampleContract8 startBlock: 66279179 mapping:10 kind: ethereum/events11 apiVersion: 0.0.912 language: wasm/assemblyscript13 file: ./src/mappings/factory.ts14 entities:15 - User16 abis:17 - name: ExampleContract18 file: ./abis/ExampleContract.json19 eventHandlers:20 - event: NewEvent(address,address)21 handler: handleNewEvent
Note: Le bloc de création du contrat peut être consulté rapidement sur Etherscan :
- Recherchez le contrat en saisissant son adresse dans la barre de recherche.
- Cliquez sur le hash de la transaction de création dans la section
Contract Creator
. - Chargez la page des détails de la transaction où vous trouverez le bloc de départ de ce contrat.
Conseils pour l’indexeur
Le paramètre indexerHints
dans le manifeste d’un Subgraph fournit des directives aux Indexeurs sur le traitement et la gestion d’un Subgraph. Il influence les décisions opérationnelles concernant le traitement des données, les stratégies d’indexation et les optimisations. Actuellement, il comporte l’option prune
pour gérer la rétention ou l’élagage des données historiques.
Cette fonctionnalité est disponible à partir de specVersion : 1.0.0
Prune
indexerHints.prune
: Définit la conservation des données de blocs historiques pour un Subgraph. Les options comprennent :
"never"
: Aucune suppression des données historiques ; conserve l’ensemble de l’historique."auto"
: Conserve l’historique minimum nécessaire tel que défini par l’Indexeur, optimisant ainsi les performances de la requête.- Un nombre spécifique : Fixe une limite personnalisée au nombre de blocs historiques à conserver.
1indexerHints:2 prune: auto
Dans le contexte des Subgraphs, le terme “historique” désigne le stockage de données reflétant les anciens états d’entités mutables.
L’historique à partir d’un bloc donné est requis pour :
- Les [requêtes chronologiques] (/subgraphs/querying/graphql-api/#time-travel-queries), qui permettent d’interroger les états passés de ces entités à des moments précis de l’histoire du Subgraph
- Utiliser le Subgraph comme base de greffage dans un autre Sugraph, au niveau de ce bloc
- Remonter le Subgraph jusqu’à ce bloc
Si les données historiques à partir du bloc ont été purgées, les capacités ci-dessus ne seront pas disponibles.
L’utilisation de "auto"
est généralement recommandée car elle maximise les performances des requêtes et est suffisante pour la plupart des utilisateurs qui n’ont pas besoin d’accéder à des données historiques étendues.
Pour les Subgraphs utilisant les requêtes chronologiques, il est conseillé de définir un nombre spécifique de blocs pour la conservation des données historiques ou d’utiliser prune : never
pour conserver tous les états historiques de l’entité. Vous trouverez ci-dessous des exemples de configuration de ces deux options dans les paramètres de votre Subgraph :
Pour conserver une quantité spécifique de données historiques :
1indexerHints:2 prune: 1000 # Remplacez 1000 par le nombre de blocs souhaité à conserver
Préserver l’histoire complète des États de l’entité :
1indexerHints:2 prune: never
SpecVersion Releases
Version | Notes de version |
---|---|
1.3.0 | Ajout de la prise en charge de la [Composition de Subgraphs] (/cookbook/subgraph-composition-three-sources) |
1.2.0 | Ajout de la prise en charge pour le Filtrage des arguments indexés & les eth_call déclarés |
1.1.0 | Prend en charge les Séries Chronologiques & Aggregations. Ajout de la prise en charge du type Int8 pour id . |
1.0.0 | Supporte la fonctionnalité indexerHints pour élaguer les Subgraphs |
0.0.9 | Supports endBlock feature |
0.0.8 | Ajout de la prise en charge de l’interrogation des Gestionnaires de blocs et des Gestionnaires d’initialisation. |
0.0.7 | Ajout de la prise en charge des fichiers sources de données. |
0.0.6 | Supports fast Proof of Indexing calculation variant. |
0.0.5 | Added support for event handlers having access to transaction receipts. |
0.0.4 | Added support for managing subgraph features. |