← Blog
10 min de lecture
|
27 oct. 2026

API d'événements de smart contracts : lecture, filtrage et abonnement

Comment fonctionne une API d'événements de smart contracts : logs, topics et décodage ABI, événements passés versus événements en direct, et quand utiliser les webhooks, WebSockets ou le polling.

Chapitres
C
Chaingateway Team
Experts blockchain

Enregistrements d'événements passant par un filtre vers deux chemins

Une API d’événements de smart contract permet à votre application de découvrir ce qu’un contrat a fait sans scanner elle-même chaque transaction. Vous interrogez les logs passés par adresse de contrat et signature d’événement, puis vous vous abonnez aux nouveaux au fur et à mesure de l’arrivée des blocs. Vous pouvez faire les deux via le RPC brut du nœud, via une bibliothèque telle qu’ethers.js, ou via une API hébergée qui décode les logs et vous les pousse sous forme de webhooks. Ce guide explique comment fonctionne chaque approche, où chacune casse, et comment choisir.

TL;DR

  • Un événement de contrat est une entrée de log écrite lorsqu’une transaction est minée. Votre application la lit après coup. Le contrat lui-même ne peut pas la lire.
  • Les événements passés proviennent d’une requête de log (eth_getLogs ou queryFilter). Les événements en direct proviennent d’un abonnement ou d’un webhook. Les abonnements de nœud ne rejouent pas l’historique.
  • Seuls les paramètres indexés peuvent être utilisés comme filtres. Le décodage nécessite l’ABI du contrat.
  • Les abonnements WebSocket meurent avec la connexion et peuvent être interrompus quand vous traitez trop lentement. Les webhooks avec une file d’attente et des gestionnaires idempotents survivent mieux aux redémarrages.
  • Une API hébergée supprime le travail sur le nœud, l’ABI et la reconnexion. C’est ce que fait Chaingateway pour les paiements et les événements de tokens.

Table des matières

Qu’est-ce qu’un événement de smart contract

Les événements sont la manière dont un contrat parle au monde extérieur. Selon ethereum.org, les événements permettent à un contrat de communiquer avec un frontend ou d’autres applications abonnées, qui peuvent traiter les informations journalisées après que la transaction est validée et ajoutée à un bloc.

Trois conséquences en découlent, et elles expliquent la plupart des confusions dans les résultats de recherche :

  1. Les événements sont une sortie, pas un stockage que vous pouvez interroger depuis Solidity. Le code du contrat écrit des logs mais ne peut pas les relire. C’est pourquoi les fils demandant comment un contrat peut accéder aux événements passés se terminent toujours par « faites-le off-chain ».
  2. Les événements n’apparaissent qu’après l’inclusion. Il n’y a pas de log pour une transaction encore dans le mempool.
  3. Les événements sont peu coûteux à émettre et peu coûteux à rechercher, c’est pourquoi les événements ERC-20 Transfer et Approval, les mints NFT et les swaps DEX sont tous suivis via les logs et non via des lectures d’état.

Une API d’événements de smart contract est tout ce qui donne à votre backend un accès structuré à ces logs : le JSON-RPC d’un nœud, une bibliothèque l’encapsulant, un indexeur, ou un service hébergé qui vous envoie des webhooks.

Ce qu’il y a dans un log d’événement

Pour filtrer ou décoder correctement les logs, il faut connaître leur structure. Selon la spécification ABI de Solidity, un log contient l’adresse du contrat, jusqu’à quatre topics et un segment de données. Les événements anonymes omettent le hash de signature de l’événement.

Pour un événement normal :

  • Topic 0 est le hash Keccak-256 de la signature de l’événement, par exemple Transfer(address,address,uint256).
  • Topics 1 à 3 contiennent les paramètres indexés.
  • Data contient les paramètres non indexés, encodés en ABI.

L’ABI sépare les paramètres en indexés, stockés sous forme de topics hashés pour un filtrage efficace, et non indexés, stockés sous forme de données binaires dans le log.

Il y a un piège à connaître. La même spécification (dans l’édition v0.8.3) indique que les paramètres indexés de longueur dynamique, tels que les chaînes de caractères et les tableaux d’octets, sont stockés sous forme de hash Keccak d’un encodage spécial plutôt que sous forme de valeur. Vous ne pouvez pas récupérer la chaîne d’origine depuis le log. Vous pouvez seulement tester si une valeur candidate correspond.

Exemple concret : Transfert ERC-20

Un log de transfert de token a le topic 0 pour la signature Transfer, l’adresse de l’expéditeur dans le topic 1, celle du destinataire dans le topic 2 et le montant dans le champ data. Si vous voulez chaque dépôt vers une adresse client, vous filtrez sur le topic 0 et le topic 2. Nous parcourons cela en détail dans notre guide de l’événement ERC-20 Transfer.

Champs du log de transfert ERC-20 et filtre de dépôt

Lecture des événements passés

Les lectures historiques sont une requête, pas un abonnement. La méthode JSON-RPC standard est eth_getLogs. Elle prend un objet filtre avec une plage de blocs, une adresse de contrat optionnelle et un tableau de topics optionnel. La référence de la documentation développeur Coinbase pour eth_getLogs montre la structure : fromBlock, toBlock et topics, et note qu’un hash de bloc peut remplacer la plage.

Les bibliothèques encapsulent cela. Dans ethers.js, contract.queryFilter(event, fromBlock, toBlock) retourne les événements correspondants, et la documentation ethers v5 sur les contrats indique que seuls les paramètres indexés peuvent être filtrés. Un paramètre laissé à null correspond à toute valeur.

Règles pratiques pour les requêtes historiques :

  • Toujours borner la plage. De nombreux fournisseurs limitent l’étendue des blocs ou le nombre de résultats par appel. Parcourez les plages par morceaux (par exemple quelques milliers de blocs à la fois) et divisez le morceau par deux en cas d’erreur.
  • Filtrez au minimum par adresse et topic 0. Les requêtes de logs non filtrées sont le moyen le plus rapide d’atteindre une limite de taux.
  • Stockez le dernier bloc traité. Ce point de contrôle permet de reprendre après un crash sans trous ni doublons.
  • Décodez avec le bon ABI. Si vous n’avez que le topic 0, vous pouvez rechercher la signature de l’événement, mais un contrat proxy peut émettre des événements définis dans son implémentation, donc utilisez l’ABI de l’implémentation.

Si vous voulez un rappel sur la communication directe avec les nœuds, notre guide JSON-RPC avec exemples en PHP, Python et JavaScript couvre le format de requête.

S’abonner aux nouveaux événements

La partie en direct fonctionne différemment, et c’est là que de nombreuses premières implémentations échouent.

La documentation sur les événements en temps réel de go-ethereum explique que les abonnements utilisent des connexions WebSocket ou IPC persistantes, généralement via eth_subscribe, et diffusent les événements au fur et à mesure que le nœud les traite. Deux limites sont importantes :

  • Pas de relecture. Les notifications d’abonnement couvrent les événements actuels, pas les passés. Si votre processus était arrêté pendant dix minutes, l’abonnement ne vous donnera pas ce que vous avez manqué. Vous comblez le retard avec une requête de logs.
  • Couplage de connexion. Les abonnements sont liés à une seule connexion. Lorsqu’elle se ferme, tous ses abonnements se ferment.

La même page indique que les nœuds mettent en file d’attente les notifications, et si votre client ne peut pas les traiter assez vite, la connexion peut être fermée une fois que la mémoire tampon atteint une limite (l’exemple de Geth est 10 000). Un gestionnaire lent qui effectue des écritures en base de données en ligne est exactement ce qui provoque cela.

Le modèle qui tient la route

Combinez les deux mécanismes :

  1. Au démarrage, lisez votre bloc de point de contrôle.
  2. Comblez le retard du point de contrôle jusqu’à la tête actuelle avec eth_getLogs, par morceaux.
  3. Ouvrez l’abonnement, et dédupliquez par hachage de transaction plus index de log.
  4. Transmettez chaque événement à une file d’attente et acquittez immédiatement. Traitez-le dans un worker.
  5. En cas de déconnexion, revenez à l’étape 1.

Cela reste correct même lorsque la connexion coupe, ce qui arrivera.

Réorganisations et confirmations

Un log que vous avez vu dans le dernier bloc peut disparaître si la chaîne se réorganise. Pour tout ce qui implique de l’argent, ne créditez pas un utilisateur dès la première détection. Attendez une profondeur de confirmation adaptée à la chaîne et au montant, et gérez le drapeau « removed » que les nœuds de type Ethereum attachent aux logs provenant de blocs orphelins. Conservez l’identifiant de l’événement traité, et rendez votre gestionnaire idempotent pour qu’un événement rejoué ou corrigé ne puisse pas créditer deux fois.

Branche d'événement orphelin à côté de la chaîne confirmée

Webhooks, WebSockets ou sondage

Les trois peuvent délivrer des événements. Ils diffèrent par qui maintient la connexion et qui assume les modes de défaillance.

ApprocheFonctionnementForceFaiblesse
SondageVotre code appelle eth_getLogs sur un minuteur depuis le dernier point de contrôleSimple, sans état, facile à reprendreLatence égale à votre intervalle, et coûte des requêtes
Abonnement WebSocketConnexion persistante qui diffuse les logs depuis un nœudLatence la plus faibleMeurt avec la connexion, pas de relecture, limites de mémoire tampon
WebhookUn service surveille la chaîne et envoie un POST HTTP à votre point de terminaisonPas de connexion longue à maintenir, fonctionne avec du serverlessVous avez besoin d’un point de terminaison public, de vérifications de signature et de gestion des doublons

Le sondage convient aux tâches back-office à faible volume. Les WebSockets conviennent à un tableau de bord ou un bot qui doit réagir dans un bloc et peut tolérer des trous. Les webhooks s’adaptent aux flux de paiement, où vous voulez une poussée fiable par événement et une file de workers derrière. Notre article sur le modèle d’ingestion, file d’attente, diffusion pour webhooks versus WebSockets examine les compromis plus en profondeur.

Gérer correctement la livraison des webhooks

Quoi qu’envoie le webhook, construisez le récepteur de la même manière :

  • Vérifiez la signature avant d’analyser le corps.
  • Retournez un 2xx rapidement et traitez de manière asynchrone.
  • Rendez les gestionnaires idempotents, indexés sur le hachage de transaction et l’index de log.
  • Attendez-vous à des tentatives de nouvelle livraison et à une livraison hors ordre.
  • Journalisez les échecs pour pouvoir les réconcilier avec une requête de log ultérieure.

Le comportement de nouvelle tentative est un sujet de conception à part entière. Pour une analyse plus approfondie de la conception autour des nouvelles tentatives et des notifications manquées, consultez cet article sur la gestion des nouvelles tentatives de webhook de paiement.

Configuration de la surveillance d’événements étape par étape

Voici un parcours minimal pour un seul contrat EVM, quel que soit l’outil utilisé.

  1. Obtenez l’ABI. À partir du code source du contrat vérifié ou de votre propre sortie de compilation. Sans cela, vous ne voyez que des topics bruts et des données hexadécimales.
  2. Choisissez les événements. Listez les signatures qui vous intéressent, telles que Transfer, Approval ou votre propre OrderPaid.
  3. Définissez les filtres. Adresse du contrat, topic 0, et tout paramètre indexé tel que le destinataire. Rappelez-vous que seules les valeurs indexées peuvent être filtrées.
  4. Effectuez le backfill. Interrogez depuis le bloc de déploiement, ou depuis votre date de début d’activité, par morceaux.
  5. Passez en production. Abonnez-vous via WebSocket, ou enregistrez un webhook.
  6. Décodez et normalisez. Convertissez les montants hexadécimaux en utilisant les décimales du token, et stockez le numéro de bloc, le hachage de transaction, l’index de log et l’adresse du contrat.
  7. Attendez la finalité. Marquez les événements comme en attente, puis confirmés.
  8. Surveillez le moniteur. Alertez lorsqu’aucun événement n’arrive depuis plus longtemps que l’écart normal de la chaîne, ou lorsque votre point de contrôle prend du retard par rapport à la tête de chaîne.

Événements à travers les chaînes

Le modèle EVM de topics et de données décodées via ABI s’applique à Ethereum, Polygon, BNB Chain et Arbitrum, donc un seul décodeur fonctionne sur eux avec différents points de terminaison RPC et règles de confirmation. Les autres réseaux ne partagent pas ce modèle. Bitcoin n’a pas de logs de contrat du tout, vous surveillez donc les adresses et les transactions. Tron et Solana ont leurs propres formats et API. Certaines piles de type Cosmos diffèrent à nouveau : Tendermint v0.36 a abandonné son API de streaming héritée au profit d’une API de log d’événements que les clients interrogent par long-polling avec des curseurs.

La conséquence pratique est qu’un produit multi-chaînes se retrouve à maintenir un adaptateur par famille de réseaux, chacun avec son propre code de reconnexion, de décodage et de finalité. C’est la partie que la plupart des équipes sous-estiment. Pour une carte des options, consultez notre comparaison des six types d’API blockchain et l’explicatif sur API blockchain versus exécution d’un nœud.

Construire soi-même ou utiliser une API hébergée

Faire tourner sa propre pile signifie un nœud (ou un point de terminaison RPC payant), un scanneur de logs, un registre d’ABI, un gestionnaire de réorganisation, une file d’attente et une configuration d’alerte. C’est raisonnable si les événements sont votre produit principal ou si vous avez besoin d’un indexage personnalisé sur des milliers de contrats.

C’est moins raisonnable si les événements sont un moyen pour une fin, comme créditer un dépôt ou confirmer une commande. Dans ce cas, vous voulez des événements décodés livrés à un point de terminaison que vous contrôlez, et rien d’autre à exploiter.

Notre perspective

La plupart des bugs de gestion d’événements que nous voyons ne concernent pas la lecture des logs. Ils concernent ce qui se passe autour : une notification manquée lors d’un déploiement, un crédit dupliqué après une nouvelle tentative, une conversion de décimales qui était erronée pour un token, une connexion qui est morte silencieusement pendant la nuit.

Nous construisons donc notre approche autour de trois convictions. Premièrement, l’application doit recevoir des données décodées et structurées, et non des topics bruts qu’elle doit interpréter. Deuxièmement, le push l’emporte sur le polling pour les paiements, à condition que chaque message soit signé et vérifiable. Troisièmement, un développeur ne devrait pas avoir à faire tourner des nœuds ou maintenir des endpoints spécifiques à chaque chaîne synchronisés simplement pour savoir qu’un paiement a été reçu.

C’est pourquoi Chaingateway expose une seule API REST sur Ethereum, Bitcoin, Tron, Solana, Polygon, BNB Chain et Arbitrum, avec des données de transaction pré-décodées, une estimation automatique des frais de gaz et des requêtes signées par HMAC. Les webhooks s’ajoutent par-dessus, afin que votre gestionnaire reçoive l’événement et que votre équipe reste concentrée sur le produit. Quel que soit votre choix, conservez le point de contrôle (checkpoint), la clé d’idempotence et la règle de confirmation. Ces trois éléments déterminent si vos chiffres sont justes.

— Bitblade

Obtenir des événements sans faire tourner de nœuds

Si votre objectif est de traiter des événements de paiement et de jetons dans une application, nos Webhooks Chaingateway délivrent des notifications blockchain en temps réel vers votre endpoint, et l’API Blockchain vous fournit des données de transaction décodées, des portefeuilles, des transferts et des estimations de frais via une interface unique. Les offres démarrent à 49 € par mois pour Plus, 99 € pour Pro, 249 € pour Premium et 499 € par mois pour Enterprise. La facturation annuelle s’élève respectivement à 490 €, 990 €, 2 490 € et 4 990 €. Consultez la page de tarification pour connaître le contenu de chaque niveau. Pour un exemple spécifique à une chaîne, lisez notre article sur les webhooks Polygon sans polling.

Sources

Recommandé

Questions fréquentes

Non. Les contrats peuvent émettre des logs mais ne peuvent pas y accéder par la suite ; les données d’événement sont donc destinées aux consommateurs hors chaîne. Si votre contrat a besoin de données historiques sur la chaîne, stockez la valeur dans l’état du contrat à la place, au coût d’un gas plus élevé.

Effectuez une requête de logs depuis votre dernier bloc traité jusqu’à la tête de chaîne actuelle. Les abonnements aux nœuds n’envoient que les événements courants, donc une reconnexion ne rejoue rien. Enregistrez un point de contrôle après chaque bloc traité et dédupliquez par hachage de transaction et index de log.

Seuls les paramètres indexés sont stockés en tant que topics, et seuls les topics peuvent être filtrés. Les valeurs non indexées se trouvent dans le champ data ; vous devez donc récupérer les logs et les filtrer dans votre propre code. Si vous contrôlez le contrat, marquez les champs sur lesquels vous chercherez comme indexés, jusqu’à trois par événement.

Pour les paiements, les webhooks avec une file d’attente sont généralement plus simples à exploiter, car vous ne maintenez pas une connexion qui peut se couper. Utilisez les WebSockets lorsque la réaction à la sous-seconde est critique et que vous pouvez combler les trous par backfill. Dans les deux cas, traitez les événements de manière idempotente et attendez suffisamment de confirmations avant de créditer les fonds.

Prêt à le construire vous-même ? Obtenir votre clé API — essai de 7 jours, sans carte bancaire — ou consultez API Blockchain pour la référence complète des endpoints.

C
Chaingateway Team
Experts blockchain

L'équipe Chaingateway s'attache à simplifier l'intégration blockchain pour les développeurs du monde entier.