Interroger et Indexer des Smart Contracts sur Morph en utilisant Goldsky

Interroger et Indexer des Smart Contracts sur Morph en utilisant Goldsky

Introduction

Imaginez ceci : vous êtes un développeur avec un tout nouveau smart contract déployé sur Morph. Votre prochain défi est de requêter et récupérer efficacement des données on-chain pour votre application décentralisée (dApp). C'est là que les subgraphs entrent en jeu. Les subgraphs offrent une manière puissante et flexible d'indexer et interroger des données de la blockchain, ce qui facilite la création de dApps réactives et riches en données.

Dans ce tutoriel, nous allons vous guider à travers le déploiement d’un smart contract sur la chaîne Morph et la mise en place d’un subgraph pour interroger ce contrat. Nous présenterons également Goldsky, un outil qui simplifie la création et la gestion des subgraphs. Commençons et voyons ce que nous pouvons construire ensemble !

Cas d'utilisation concrets des Subgraphs

Les subgraphs sont extrêmement utiles dans divers scénarios tels que :

  • Finance Décentralisée (DeFi) : Indexer et interroger les volumes de trading, les pools de liquidité et les échanges de tokens.

  • Marchés de NFT : Suivi de la propriété, des ventes et des métadonnées des NFT.

  • Gouvernance DAO : Récupérer les détails des propositions, les décomptes de voix et les informations des participants.

  • Gestion de la Chaîne d'Approvisionnement : Suivre le flux des biens et vérifier les transactions.

Qu'est-ce qu'un Subgraph ?

Un subgraph est un moyen d'ingérer, traiter et indexer des données provenant d'une blockchain. Il vous permet de définir quelles données indexer et comment les stocker, facilitant leur requête ultérieure. Les subgraphs sont accessibles via des APIs GraphQL, permettant aux développeurs d’interroger les données des transactions en temps réel. Ils sont particulièrement utiles pour les développeurs de smart contracts complexes qui nécessitent des interfaces frontend robustes.

Pourquoi utiliser un Subgraph au lieu de requêtes directes sur le contrat ?

Vous pourriez vous demander : « Pourquoi ne pas simplement interroger le contrat directement en utilisant des outils comme Wagmi ? ». Voici quelques raisons pour lesquelles les subgraphs sont souvent un meilleur choix :

  • Efficacité : Les requêtes directes peuvent être inefficaces et lentes, surtout pour des ensembles de données volumineux. Les subgraphs indexent les données hors chaîne, permettant des requêtes plus rapides et plus efficaces.

  • Requêtes complexes : Les subgraphs permettent des requêtes plus complexes, impliquant des filtres, des tris et des agrégations, difficiles à réaliser directement sur la chaîne.

  • Réduction de la charge : En déchargeant le traitement des données sur les subgraphs, vous réduisez la charge computationnelle sur la blockchain, ce qui est bénéfique pour la performance de votre dApp et la santé du réseau.

  • Expérience utilisateur : Un accès plus rapide aux données améliore l'expérience utilisateur, rendant votre dApp plus réactive et engageante.

Présentation de Goldsky

Goldsky est un fournisseur de services d’indexation de données performant pour Morph. Il facilite l'extraction, la transformation et le chargement des données on-chain, tant pour les applications que pour les analyses.

Goldsky propose une interface intuitive et des fonctionnalités puissantes qui simplifient votre flux de travail de développement, vous permettant de vous concentrer sur la construction de votre dApp sans vous soucier des complexités de l'indexation des données.

Que construisons-nous ?

Dans ce tutoriel, nous allons créer un subgraph qui indexe les données de notre dApp immobilière fractionnée. Nous utiliserons ce subgraph pour interroger des détails sur les propriétés, notamment les parts de propriété, les prix, etc.

À la fin de ce tutoriel, vous aurez un subgraph fonctionnel et les connaissances nécessaires pour créer des applications riches en données.

Mise en place de votre environnement

Avant de commencer à construire, configurons notre environnement. Nous aurons besoin de quelques outils et dépendances pour tout faire fonctionner.

Prérequis

  • Node et npm : Assurez-vous d'avoir Node.js et npm installés. Vous pouvez les télécharger depuis nodejs.org.

  • Git : Vous aurez besoin de Git pour le contrôle de version.

  • Graph CLI : Le graphcli est essentiel pour créer et déployer des subgraphs.

npm install -g @graphprotocol/graph-cli

Pour les utilisateurs de Mac, pensez à exécuter cette commande avec "sudo".

Configuration d'un nouveau projet

mkdir  morph-goldsky    
cd morph-goldsky

Création de votre subgraph

Créez un fichier package.json en exécutant la commande suivante dans votre terminal :

yarn  init -y
yarn add @graphprotocol/graph-ts

La commande ci-dessus crée un fichier package.json et installe les types du protocole Graph.

Dans le répertoire racine de votre projet, suivez ces étapes pour configurer les fichiers et dossiers nécessaires :

  1. Créez un dossier nommé abis et à l'intérieur, un fichier nommé Okido.json.

  2. Créez un autre dossier nommé src et à l'intérieur, un fichier nommé mapping.ts.

  3. Dans le répertoire racine, créez deux fichiers supplémentaires : schema.graphql et subgraph.yaml.

Votre répertoire de projet ( project directory) devrait ressembler à ceci :

Ajout de l'ABI

Dans votre fichier /abis/Okido.json, collez l'ABI (Application Binary Interface) de la plateforme Okido finance. Vous pouvez accéder à l'ABI ici.

Définir le schéma

Allez dans le fichier schema.graphql et collez le schéma suivant. Ce schéma définit les types et les relations entre nos différentes entités.

type Property @entity {
  id: ID!
  tokenId: BigInt!
  fractionalContract: Bytes!
  pricePerShare: BigInt!
  totalShares: BigInt!
  sharesSold: BigInt!
  name: String!
  uri: String!
  shares: [Share!]! @derivedFrom(field: "property")
}

type Share @entity {
  id: ID!
  property: Property!
  owner: User!
  shares: BigInt!
  purchaseTimestamp: BigInt!
}

type User @entity {
  id: ID!
  properties: [Share!]! @derivedFrom(field: "owner")
}

type PropertyCreated @entity {
  id: ID!
  tokenId: BigInt!
  fractionalContract: Bytes!
  pricePerShare: BigInt!
  timestamp: BigInt!
}

type SharesPurchased @entity {
  id: ID!
  tokenId: BigInt!
  buyer: User!
  shares: BigInt!
  timestamp: BigInt!
}

Écrire les mappings

Ouvrez le fichier src/mapping.ts et définissez les gestionnaires des événements émis par votre smart contract. Ces fonctions constituent la logique qui s'exécutera lorsqu'un événement sera émis. La fonction dans nos mappings nous permet de récupérer toutes les propriétés, utilisateurs et données des parts. Vous pouvez copier les mappings pour notre projet ci-dessous :

import { BigInt } from "@graphprotocol/graph-ts";
import {Okido, PropertyCreated as PropertyCreatedEvent, SharesPurchased as SharesPurchasedEvent,
} from "../generated/OkidoFinance Subgraph/Okido";
import { Property,Share,User,PropertyCreated, SharesPurchased} from "../generated/schema";

export function handlePropertyCreated(event: PropertyCreatedEvent): void {
  let property = new Property(event.params.tokenId.toString());
  property.tokenId = event.params.tokenId;
  property.fractionalContract = event.params.fractionalContract;
  property.pricePerShare = event.params.pricePerShare;
  property.totalShares = BigInt.fromI32(0);
  property.sharesSold = BigInt.fromI32(0);
  property.name = event.params.name;
  property.uri = event.params.uri;
  property.save();

  let propertyCreated = new PropertyCreated(
    event.transaction.hash.toHex() + "-" + event.logIndex.toString()
  );
  propertyCreated.tokenId = event.params.tokenId;
  propertyCreated.fractionalContract = event.params.fractionalContract;
  propertyCreated.pricePerShare = event.params.pricePerShare;
  propertyCreated.timestamp = event.block.timestamp;
  propertyCreated.save();
}

export function handleSharesPurchased(event: SharesPurchasedEvent): void {
  let shareId =
    event.params.tokenId.toString() + "-" + event.params.buyer.toHex();
  let share = Share.load(shareId);
  if (share == null) {
    share = new Share(shareId);
    share.property = event.params.tokenId.toString();
    share.owner = event.params.buyer.toHex();
    share.shares = BigInt.fromI32(0);
    share.purchaseTimestamp = event.block.timestamp;
  }
  share.shares = share.shares.plus(event.params.shares);
  share.save();

  let property = Property.load(event.params.tokenId.toString());
  if (property != null) {
    property.sharesSold = property.sharesSold.plus(event.params.shares);
    property.save();
  }

  let user = User.load(event.params.buyer.toHex());
  if (user == null) {
    user = new User(event.params.buyer.toHex());
  }
  user.save();

  let sharesPurchased = new SharesPurchased(
    event.transaction.hash.toHex() + "-" + event.logIndex.toString()
  );
  sharesPurchased.tokenId = event.params.tokenId;
  sharesPurchased.buyer = event.params.buyer.toHex();
  sharesPurchased.shares = event.params.shares;
  sharesPurchased.timestamp = event.block.timestamp;
  sharesPurchased.save();
}

Configurer le subgraph/manifeste

Naviguez jusqu'au fichier subgraph.yaml à la racine de votre projet et configurez-le pour indexer les événements de votre smart contract. Copiez le manifeste ci-dessous et collez-le dans votre projet.

specVersion: 0.0.4

schema:
  file: ./schema.graphql
dataSources:
  - kind: ethereum
    name: OkidoFinance Subgraph
    network: morph-testnet
    source:
      address: "0xC97acACa1ed181d88aE2B86Fd49AE66482083B28"
      abi: Okido
      startBlock: 4132207
    mapping:
      kind: ethereum/events
      apiVersion: 0.0.7
      language: wasm/assemblyscript
      entities:
        - Property
        - Share
        - User
        - PropertyCreated
        - SharesPurchased
      abis:
        - name: Okido
          file: ./abis/Okido.json
      eventHandlers:
        - event: PropertyCreated(indexed uint256,indexed address,uint256,string,string)
          handler: handlePropertyCreated
        - event: SharesPurchased(indexed uint256,indexed address,uint256)
          handler: handleSharesPurchased
      file: ./src/mapping.ts

Dans ce manifeste :

  • Source : L'adresse pointe vers l'adresse de déploiement de la dApp Okido finance, et le startBlock fait référence au bloc à partir duquel nous souhaitons commencer l'indexation. Dans ce cas, il s'agit du bloc où le contrat a été déployé. Vous pouvez obtenir ces détails depuis l'explorateur Morph Holesky.

  • Entités : Cela fait référence aux types que nous avons créés dans notre schéma. Pour notre projet, nous avons cinq entités.

  • Gestionnaires d'événements : Cela spécifie l'événement du smart contract que nous indexons (dans ce cas, Okido finance. Vous pouvez consulter le contrat [ici]) et les gestionnaires qui exécutent la logique décrite dans notre fichier mappings.ts.

Construire le subgraph

Dans votre terminal, exécutez :

graph codegen

Cela génère les types et charge l'ABI de notre projet. Ensuite, vous exécutez :

graph  build

Déployer sur Goldsky

Déployer notre subgraph sur Goldsky est vraiment simple, il suffit de quelques étapes.

  1. Allez sur app.goldsky.com dans votre navigateur pour créer un compte.

  2. Créez une clé API sur la page des paramètres.

  3. Installez l'outil en ligne de commande (CLI) de Goldsky et connectez-vous :

curl https://goldsky.com | sh

Exécutez la commande de connexion et ajoutez la clé API créée précédemment :

goldsky login

Déployer le subgraph

Pour déployer votre subgraph, exécutez la commande suivante :

goldsky subgraph deploy okido-subgraph/1.0.5 --path

Et voilà ! Vous devriez recevoir un message indiquant que votre subgraph a été déployé. Vous devriez également pouvoir voir votre subgraph déployé sur le tableau de bord de votre projet.

Interroger notre subgraph

Nous allons effectuer deux requêtes pour tester notre subgraph :

  1. Récupérer toutes les propriétés.

  2. Récupérer une seule propriété en utilisant son identifiant de jeton.

Récupérer toutes les propriétés

Pour ce faire, cliquez sur le lien public de GraphQL pour ouvrir le playground GraphQL. Ensuite, exécutez la requête ci-dessous pour récupérer toutes les propriétés.

query Properties{
  properties {
    id
    tokenId
    pricePerShare
    totalShares
    sharesSold
    fractionalContract
    name
    uri
    shares {
      id
      owner {
        id
      }
      shares
      purchaseTimestamp
    }
  }
}

Vous devriez obtenir le résultat de notre requête, qui liste toutes les propriétés créées ainsi que les détails de partage pour chacune.

Récupérer une seule propriété avec un identifiant de jeton

Pour récupérer une seule propriété avec un identifiant (ID), nous allons modifier notre requête comme suit :

query Properties{
  properties {
    id
    tokenId
    pricePerShare
    totalShares
    sharesSold
    fractionalContract
    name
    uri
    shares {
      id
      owner {
        id
      }
      shares
      purchaseTimestamp
    }
  }
}

Conclusion

Félicitations ! Vous avez réussi à créer un subgraph pour interroger les données d'un smart contract déployé sur la chaîne Morph. Vous avez appris à définir un schéma, mapper les événements de votre contrat, et déployer votre subgraph avec Goldsky. Ce subgraph vous permet d'interroger et d'indexer efficacement les données de la blockchain, offrant un outil puissant pour développer des applications plus réactives et dynamiques.

Si vous avez trouvé ce guide utile, laissez un commentaire. Vous pouvez consulter le code complet de ce projet [ici]. Si vous avez des questions ou rencontrez des difficultés, créez une issue sur GitHub ou contactez-nous sur Discord.

Website | Twitter |Discord | Telegram | MediumLinkedin