Skip to content
Learni
View all tutorials
Web3

Comment créer un subgraph avec The Graph en 2026

Introduction

The Graph est un protocole décentralisé qui indexe et organise les données des blockchains comme Ethereum, permettant des requêtes GraphQL ultra-rapides. Imaginez un Google pour la blockchain : au lieu de scanner des millions de blocs, vous queryez un subgraph optimisé.

Pourquoi l'utiliser en 2026 ? Avec l'essor des dApps DeFi et NFT, les données on-chain explosent. Les subgraphs évitent les nœuds RPC lents et coûteux, rendant vos apps scalables. Ce tutoriel beginner vous guide pas à pas pour créer un subgraph indexant les transferts d'un token ERC20 (ex: USDC). Vous obtiendrez un code 100% fonctionnel, déployable sur le Hosted Service de The Graph. À la fin, vous queryerez vos données en temps réel. Durée : 30 min. Prêt à booster vos projets Web3 ?

Prérequis

  • Node.js 18+ et npm/yarn installés
  • Compte gratuit sur The Graph Hosted Service
  • Clé API subgraph (créez-en une après inscription)
  • Connaissances basiques JavaScript/TypeScript
  • MetaMask ou Infura pour ABI (optionnel, on utilisera un exemple public)

Installer Graph CLI

terminal
npm install -g @graphprotocol/graph-cli
npm install -g @graphprotocol/graph-node
npm install -g @graphprotocol/graph-ts

Graph CLI est l'outil en ligne de commande officiel pour créer, build et déployer les subgraphs. L'installation globale permet d'exécuter graph partout. Vérifiez avec graph --version : doit afficher 0.38+. Évitez les versions anciennes pour compatibilité 2026.

Créer le projet subgraph

Créez un dossier projet et initialisez le squelette. Nous ciblerons les transferts ERC20 du contrat USDC (0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 sur Ethereum Mainnet). Cela indexera tous les événements Transfer.

Initialiser le subgraph

terminal
mkdir erc20-transfers-subgraph
cd erc20-transfers-subgraph
graph init --studio erc20-transfers

# Suivez les prompts :
# Network: mainnet
# Contract: 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
# ABI: Copiez depuis Etherscan ou fournissez un fichier local
# Start Block: 12287507 (premier bloc USDC)

La commande graph init génère la structure : subgraph.yaml, schema.graphql, dossiers abis/ et src/. Spécifiez le contrat USDC pour auto-générer l'ABI. Le start block optimise l'indexation en ignorant les blocs vides. Piège : sans ABI valide, le build échoue.

Configurer subgraph.yaml

subgraph.yaml
specVersion: 0.0.5
graphqlSchema: ./schema.graphql
schemaFile: ./schema.graphql
packageManager: npm

source:
  abi: ERC20
  address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
  startBlock: 12287507
  network: mainnet

dataSources:
  - kind: ethereum/contract
    name: ERC20
    source:
      abi: ERC20
      address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
      startBlock: 12287507
    mapping:
      entities:
        - Transfer
      abis:
        - name: ERC20
          file: ./abis/ERC20.json
      eventHandlers:
        - event: Transfer(indexed address,indexed address,uint256)
          handler: handleTransfer
      file: ./src/erc20.ts

Ce fichier YAML définit la source (contrat Ethereum), les événements à écouter (Transfer) et le mapping handler. specVersion: 0.0.5 est standard en 2026. Le startBlock accélère l'indexation. Piège : adresse en checksum (majuscules) pour éviter les erreurs de résolution.

Définir le schema GraphQL

Le schema décrit les entités à indexer, comme une DB relationnelle en GraphQL. Nous stockerons chaque Transfer avec from/to/value/block.

Écrire schema.graphql

schema.graphql
type Transfer @entity {
  id: ID!
  from: Bytes! # address
  to: Bytes!   # address
  value: BigInt!
  blockNumber: BigInt!
  blockTimestamp: BigInt!
  transactionHash: Bytes!
}

type ERC20 @entity {
  id: ID!
  totalSupply: BigInt!
  symbol: String!
  name: String!
}

Les types Transfer et ERC20 sont des entités persistantes. Bytes pour adresses/hex, BigInt pour uint256 (valeurs > JS Number). @entity active l'indexation. Après modification, relancez graph codegen. Piège : oubliez ! sur champs non-nullables, les queries planteront.

Générer code et ABI

terminal
graph codegen
graph build

graph codegen génère les types TypeScript dans generated/ à partir du schema et ABI. graph build compile les mappings en WASM. Vérifiez build/subgraph.sol.json sans erreurs. Essentiel avant déploiement.

Implémenter les mappings

Les mappings en AssemblyScript traitent les événements blockchain. Comme des hooks : à chaque Transfer, on sauve l'entité.

Écrire le mapping erc20.ts

src/erc20.ts
import { Transfer as TransferEvent } from "../generated/ERC20/ERC20";
import { Transfer, ERC20 } from "../generated/schema";
import { BigInt, Bytes } from "@graphprotocol/graph-ts";

export function handleTransfer(event: TransferEvent): void {
  let transfer = new Transfer(event.transaction.hash.toHex() + "-" + event.logIndex.toString());
  transfer.from = event.params.from;
  transfer.to = event.params.to;
  transfer.value = event.params.value;
  transfer.blockNumber = event.block.number;
  transfer.blockTimestamp = event.block.timestamp;
  transfer.transactionHash = event.transaction.hash;
  transfer.save();

  // Update ERC20 entity
  let token = ERC20.load("current");
  if (token == null) {
    token = new ERC20("current");
    token.symbol = "USDC";
    token.name = "USD Coin";
    token.totalSupply = BigInt.fromI32(0);
  }
  token.save();
}

À chaque événement Transfer, on crée une entité Transfer avec ID unique (tx hash + log index). On met à jour l'entité ERC20. save() persiste en IPFS/Indexeur. AssemblyScript est strict : utilisez BigInt pour les grands nombres. Piège : ID dupliqués causent des overwrites.

Télécharger ABI ERC20

abis/ERC20.json
{"abiVersion":2,"version":"erc20:1.0.0","types":{"TransferEvent":{"fields":[{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}]},"ApprovalEvent":{"fields":[{"name":"owner","type":"address","indexed":true},{"name":"spender","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}]},"TransferResult":{"type":"boolean"},"ApprovalResult":{"type":"boolean"},"TransferResultWithReturnData":{"data":{"type":"bytes"},"success":{"type":"boolean"}},"ApprovalResultWithReturnData":{"data":{"type":"bytes"},"success":{"type":"boolean"}}},"functions":[{"name":"allowance","inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"name":"approve","inputs":[{"name":"spender","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"TransferResult"}]},{"name":"balanceOf","inputs":[{"name":"account","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8"}]},{"name":"name","inputs":[],"outputs":[{"name":"","type":"string"}]},{"name":"symbol","inputs":[],"outputs":[{"name":"","type":"string"}]},{"name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"name":"transfer","inputs":[{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"TransferResult"}]},{"name":"transferFrom","inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"TransferResult"}]}],
"events":["TransferEvent","ApprovalEvent"]}

L'ABI définit les événements et fonctions du contrat ERC20. Téléchargez-le depuis Etherscan (USDC) et placez en abis/ERC20.json. Format JSON standard IPFS. Sans ça, les mappings ne reconnaissent pas les params. Piège : ABI tronqué = événements ignorés.

Déployer le subgraph

terminal
graph auth --studio YOUR_API_KEY

graph deploy --studio erc20-transfers

# Ou pour Hosted Service:
graph deploy --service-name mainnet YOUR_SUBGRAPH_ID --ipfs https://api.thegraph.com/ipfs/

Authentifiez avec votre clé API. graph deploy build, upload sur IPFS et déploie sur Hosted Service. Remplacez YOUR_API_KEY et YOUR_SUBGRAPH_ID. Surveillez le dashboard pour sync. Temps : 5-10 min pour 1M+ transfers. Piège : oubli d'auth = 401 error.

Query le subgraph

Une fois déployé, queryez via GraphQL Playground : https://api.studio.thegraph.com/query/YOUR_ID/erc20-transfers/version/latest. Exemple query :

``graphql
query {
transfers(first: 10, orderBy: blockTimestamp, orderDirection: desc) {
id
from
to
value
blockTimestamp
}
}
``
Résultat : JSON avec 10 derniers transfers USDC.

Bonnes pratiques

  • Commencez par un startBlock récent : Réduit le temps d'indexation de jours à minutes.
  • Utilisez des IDs composites : tx.hash + logIndex évite les doublons.
  • Limitez les entités : Indexez seulement les events nécessaires pour scaler.
  • Testez localement : graph test avant deploy.
  • Migrez vers décentralisé : Après Hosted, passez à L2/Substreams en 2026.

Erreurs courantes à éviter

  • ABI manquant/invalide : graph codegen échoue → Téléchargez toujours depuis source fiable.
  • BigInt vs Number : Overflow sur values > 2^53 → Toujours BigInt.fromString().
  • Pas de .save() : Entités non persistées → Vérifiez chaque handler.
  • StartBlock trop bas : Indexation infinie → Visez > 10M pour mainnet.

Pour aller plus loin

  • Docs officielles : The Graph Docs
  • Exemple avancé : Subgraphs Uniswap V3
  • Formations Learni Web3 : Maîtrisez Solidity + The Graph en 20h.
  • Outils : SubQuery (alternative), Goldsky (hosted).
Comment créer un subgraph The Graph 2026 (Tutoriel) | Learni