Guide pour créer un écouteur d'événements frontend pour smart contracts blockchain. Surveillez l'état en temps réel, intégrez Web3.js/ethers.js et mettez à jour votre UI.
Écouteur d'Événements de Smart Contract Blockchain Frontend : Surveillance de l'État du Contrat
Les applications décentralisées (DApps) nécessitent souvent des mises à jour en temps réel pour refléter les changements d'état du smart contract sous-jacent. C'est là que les écouteurs d'événements entrent en jeu. En surveillant les événements émis par les smart contracts, les applications frontend peuvent réagir aux transitions d'état et fournir aux utilisateurs des informations à jour. Ce guide offre un aperçu complet de la création d'un écouteur d'événements frontend pour les smart contracts blockchain, en se concentrant sur la mise en œuvre pratique et les meilleures pratiques.
Que sont les Événements de Smart Contract ?
Les smart contracts, écrits dans des langages comme Solidity, peuvent émettre des événements lorsque des actions spécifiques se produisent au sein du contrat. Ces événements servent de mécanisme de notification, signalant aux applications externes qu'un changement d'état a eu lieu. Considérez-les comme des entrées de journal qui sont enregistrées de manière permanente sur la blockchain. Les événements contiennent des informations sur le changement, permettant aux applications de réagir en conséquence.
Par exemple, considérons un simple contrat de jeton. Il pourrait émettre un événement lorsque des jetons sont transférés entre des comptes. Cet événement inclurait généralement l'adresse de l'expéditeur, l'adresse du destinataire et le montant transféré. Une application frontend pourrait écouter cet événement et mettre à jour le solde de l'utilisateur en temps réel.
Pourquoi Utiliser des Écouteurs d'Événements ?
Interroger (polling) la blockchain pour des changements d'état est inefficace et gourmand en ressources. Les écouteurs d'événements offrent une solution plus élégante et efficace en permettant aux applications d'attendre passivement les notifications. Cela réduit la charge sur la blockchain et améliore la réactivité de la DApp.
Les principaux avantages de l'utilisation des écouteurs d'événements incluent :
- Mises à jour en temps réel : Fournir aux utilisateurs un retour immédiat sur les changements d'état du contrat.
- Efficacité améliorée : Réduire le besoin d'interroger constamment la blockchain.
- Expérience utilisateur améliorée : Créer une application plus dynamique et réactive.
- Coûts de gaz réduits : Éviter les opérations de lecture inutiles sur la blockchain.
Outils et Technologies
Plusieurs outils et bibliothèques peuvent être utilisés pour créer des écouteurs d'événements frontend. Les options les plus populaires incluent :
- Web3.js : Une bibliothèque JavaScript qui vous permet d'interagir avec les nœuds et les smart contracts Ethereum. Elle fournit une API complète pour accéder aux données de la blockchain, envoyer des transactions et écouter les événements.
- Ethers.js : Une autre bibliothèque JavaScript populaire pour interagir avec Ethereum. Elle est connue pour sa simplicité, sa sécurité et ses performances.
- Infura/Alchemy : Des fournisseurs d'infrastructure qui offrent un accès fiable au réseau Ethereum. Ils fournissent des API pour lire les données de la blockchain et envoyer des transactions, éliminant le besoin de gérer votre propre nœud Ethereum.
- WebSockets : Un protocole de communication qui permet une communication bidirectionnelle en temps réel entre un client et un serveur. Les WebSockets sont souvent utilisés pour transmettre les notifications d'événements au frontend.
Créer un Écouteur d'Événements Frontend : Un Guide Étape par Étape
Cette section décrit les étapes nécessaires à la création d'un écouteur d'événements frontend en utilisant Web3.js ou ethers.js.
Étape 1 : Configurer votre Environnement de Développement
Avant de commencer, assurez-vous d'avoir installé les éléments suivants :
- Node.js : Un environnement d'exécution JavaScript.
- npm (Node Package Manager) ou yarn : Un gestionnaire de paquets pour installer les dépendances.
- Un éditeur de code : Visual Studio Code, Sublime Text, ou tout autre éditeur de votre choix.
Créez un nouveau répertoire de projet et initialisez-le avec npm ou yarn :
mkdir my-dapp
cd my-dapp
npm init -y
Ou en utilisant yarn :
mkdir my-dapp
cd my-dapp
yarn init -y
Étape 2 : Installer les Dépendances
Installez Web3.js ou ethers.js, ainsi que toute autre dépendance nécessaire. Par exemple, vous pourriez avoir besoin d'une bibliothèque pour gérer les variables d'environnement.
En utilisant npm :
npm install web3 dotenv
En utilisant yarn :
yarn add web3 dotenv
Ou pour ethers.js :
En utilisant npm :
npm install ethers dotenv
En utilisant yarn :
yarn add ethers dotenv
Étape 3 : Configurer votre Fournisseur Web3
Vous devrez configurer un fournisseur Web3 pour vous connecter au réseau Ethereum. Cela peut être fait en utilisant Infura, Alchemy, ou un nœud Ethereum local (comme Ganache).
Créez un fichier `.env` dans le répertoire de votre projet et ajoutez votre clé API Infura ou Alchemy :
INFURA_API_KEY=VOTRE_CLE_API_INFURA
Ensuite, dans votre fichier JavaScript, configurez le fournisseur Web3 :
Avec Web3.js :
require('dotenv').config();
const Web3 = require('web3');
const infuraApiKey = process.env.INFURA_API_KEY;
const web3 = new Web3(new Web3.providers.WebsocketProvider(`wss://mainnet.infura.io/ws/v3/${infuraApiKey}`));
Avec ethers.js :
require('dotenv').config();
const { ethers } = require('ethers');
const infuraApiKey = process.env.INFURA_API_KEY;
const provider = new ethers.providers.WebSocketProvider(`wss://mainnet.infura.io/ws/v3/${infuraApiKey}`);
Note : Remplacez `mainnet` par le réseau approprié (par exemple, `ropsten`, `rinkeby`, `goerli`) si vous utilisez un réseau de test.
Étape 4 : Obtenir l'ABI et l'Adresse du Contrat
Pour interagir avec votre smart contract, vous aurez besoin de son Interface Binaire d'Application (ABI) et de son adresse. L'ABI est un fichier JSON qui décrit les fonctions et les événements du contrat. L'adresse est l'emplacement du contrat sur la blockchain.
Vous pouvez obtenir l'ABI à partir de la sortie de votre compilateur Solidity. L'adresse sera affichée après le déploiement du contrat.
Stockez l'ABI dans un fichier JSON (par exemple, `MyContract.json`) et l'adresse dans votre fichier `.env` :
CONTRACT_ADDRESS=0xVotreAdresseDeContrat...
Étape 5 : Créer une Instance de Contrat
En utilisant l'ABI et l'adresse, créez une instance de contrat dans votre fichier JavaScript :
Avec Web3.js :
const contractAddress = process.env.CONTRACT_ADDRESS;
const contractABI = require('./MyContract.json').abi;
const myContract = new web3.eth.Contract(contractABI, contractAddress);
Avec ethers.js :
const contractAddress = process.env.CONTRACT_ADDRESS;
const contractABI = require('./MyContract.json').abi;
const myContract = new ethers.Contract(contractAddress, contractABI, provider);
Étape 6 : Écouter les Événements
Maintenant, vous pouvez commencer à écouter les événements émis par votre smart contract. Utilisez la propriété `events` de votre instance de contrat pour vous abonner aux événements.
Avec Web3.js :
myContract.events.MyEvent({
filter: {myIndexedParam: [20,23]}, // Filtre optionnel utilisant des paramètres indexés.
fromBlock: 'latest' // Commencer l'écoute à partir du dernier bloc.
}, function(error, event){
if(!error)
{console.log(event);}
else
{console.log(error);}
})
.on('data', function(event){
console.log(event);
})
.on('changed', function(event){
// supprimer l'événement de la base de données locale
})
.on('error', console.error);
Ou, en utilisant async/await :
myContract.events.MyEvent({
filter: {myIndexedParam: [20,23]}, // Filtre optionnel utilisant des paramètres indexés.
fromBlock: 'latest' // Commencer l'écoute à partir du dernier bloc.
})
.on('data', async function(event){
console.log(event);
// Traitez les données de l'événement ici, par ex., mettre à jour l'UI
try {
// Exemple : Interagir avec une autre partie de votre DApp.
// await uneAutreFonction(event.returnValues);
} catch (error) {
console.error("Erreur lors du traitement de l'événement :", error);
}
})
.on('changed', function(event){
// supprimer l'événement de la base de données locale
})
.on('error', console.error);
Avec ethers.js :
myContract.on("MyEvent", (param1, param2, event) => {
console.log("Événement MyEvent émis !");
console.log("Param1 :", param1);
console.log("Param2 :", param2);
console.log("Données de l'événement :", event);
// Traitez les données de l'événement ici, par ex., mettre à jour l'UI
});
Dans les deux exemples, remplacez `MyEvent` par le nom de l'événement que vous souhaitez écouter. La fonction de rappel (callback) sera exécutée chaque fois que l'événement est émis. Vous pouvez accéder aux données de l'événement via l'objet `event`.
Étape 7 : Gérer les Données des Événements
L'objet `event` contient des informations sur l'événement, y compris les arguments qui lui ont été passés, le numéro de bloc et le hash de la transaction. Vous pouvez utiliser ces données pour mettre à jour l'interface utilisateur de votre application ou effectuer d'autres actions.
Par exemple, si votre événement inclut le solde d'un utilisateur, vous pouvez mettre à jour l'affichage du solde sur le frontend :
// À l'intérieur du gestionnaire d'événements
const balance = event.returnValues.balance; // Web3.js
// Ou
// const balance = param1; // ethers.js, en supposant que param1 est le solde
document.getElementById('balance').textContent = balance;
Techniques Avancées d'Écoute d'Événements
Cette section explore quelques techniques avancées pour créer des écouteurs d'événements plus sophistiqués.
Filtrer les Événements
Vous pouvez filtrer les événements en fonction de critères spécifiques, tels que la valeur d'un paramètre indexé. Cela peut vous aider à affiner les événements qui vous intéressent et à réduire la quantité de données à traiter.
Dans Web3.js, vous pouvez utiliser l'option `filter` lors de l'abonnement aux événements :
myContract.events.MyEvent({
filter: {myIndexedParam: [20, 23]}, // N'écouter que les événements où myIndexedParam est 20 ou 23.
fromBlock: 'latest'
}, function(error, event){
console.log(event);
})
Dans ethers.js, vous pouvez spécifier des filtres lors de la création de l'instance de contrat ou lors de l'attachement de l'écouteur d'événements :
// Filtrer par nom d'événement et arguments indexés
const filter = myContract.filters.MyEvent(arg1, arg2);
myContract.on(filter, (arg1, arg2, event) => {
console.log("Événement MyEvent émis avec des arguments spécifiques !");
console.log("Arg1 :", arg1);
console.log("Arg2 :", arg2);
console.log("Données de l'événement :", event);
});
Écouter les Événements Passés
Vous pouvez récupérer les événements passés qui se sont produits avant que votre écouteur d'événements ne soit actif. Cela peut être utile pour initialiser l'état de votre application ou à des fins d'audit.
Dans Web3.js, vous pouvez utiliser la méthode `getPastEvents` :
myContract.getPastEvents('MyEvent', {
fromBlock: 0,
toBlock: 'latest'
}, function(error, events){
console.log(events);
});
Dans ethers.js, vous pouvez interroger les journaux d'événements en utilisant la méthode `getLogs` du fournisseur :
const blockNumber = await provider.getBlockNumber();
const filter = myContract.filters.MyEvent(arg1, arg2);
const logs = await provider.getLogs({
address: myContract.address,
fromBlock: blockNumber - 1000, // les 1000 derniers blocs
toBlock: blockNumber,
topics: filter.topics // sujets du filtre
});
for (const log of logs) {
const parsedLog = myContract.interface.parseLog(log);
console.log(parsedLog);
}
Gérer les Transactions Annulées (Reverted)
Les transactions peuvent parfois être annulées (revert) en raison d'erreurs ou de gaz insuffisant. Lorsqu'une transaction est annulée, les événements associés à cette transaction ne sont pas émis. Il est important de gérer les transactions annulées avec élégance pour éviter un comportement inattendu dans votre application.
Une façon de gérer les transactions annulées est de surveiller le reçu de la transaction (transaction receipt). Le reçu contient des informations sur la transaction, y compris son statut (succès ou échec). Si le statut est `0x0`, la transaction a été annulée.
Vous pouvez utiliser la méthode `web3.eth.getTransactionReceipt` (Web3.js) ou `provider.getTransactionReceipt` (ethers.js) pour récupérer le reçu de la transaction.
Utiliser les WebSockets pour les Mises à Jour en Temps Réel
Les WebSockets fournissent une connexion persistante entre le client et le serveur, permettant une communication bidirectionnelle en temps réel. C'est idéal pour transmettre les notifications d'événements au frontend.
Web3.js et ethers.js prennent tous deux en charge les WebSockets. Pour utiliser les WebSockets, configurez votre fournisseur Web3 avec un point de terminaison WebSocket (comme montré dans les exemples de configuration ci-dessus).
Considérations de Sécurité
Lors de la création d'écouteurs d'événements frontend, il est important de prendre en compte les aspects de sécurité suivants :
- Validation des données : Validez toujours les données des événements avant de les utiliser dans votre application. Ne faites pas aveuglément confiance aux données reçues de la blockchain.
- Gestion des erreurs : Mettez en œuvre une gestion des erreurs robuste pour prévenir les comportements inattendus et les vulnérabilités de sécurité potentielles.
- Limitation de débit (Rate Limiting) : Mettez en œuvre une limitation de débit pour prévenir les abus et protéger votre application contre les attaques par déni de service.
- Gestion des dépendances : Maintenez vos dépendances à jour pour corriger les vulnérabilités de sécurité.
- Assainissement des entrées utilisateur : Si vous affichez des données d'événements aux utilisateurs, assainissez les données pour prévenir les attaques de type cross-site scripting (XSS).
Meilleures Pratiques
Suivez ces meilleures pratiques pour créer des écouteurs d'événements frontend robustes et maintenables :
- Utilisez une architecture modulaire : Décomposez votre application en composants plus petits et réutilisables.
- Écrivez des tests unitaires : Testez minutieusement vos écouteurs d'événements pour vous assurer qu'ils fonctionnent correctement.
- Utilisez un framework de journalisation (logging) : Enregistrez les événements importants et les erreurs pour vous aider à déboguer votre application.
- Documentez votre code : Documentez clairement votre code pour le rendre plus facile à comprendre et à maintenir.
- Suivez les conventions de codage : Adhérez à des conventions de codage cohérentes pour améliorer la lisibilité et la maintenabilité.
- Surveillez votre application : Surveillez les performances et l'utilisation des ressources de votre application pour identifier les goulots d'étranglement potentiels.
Scénario d'Exemple : Surveiller un Transfert de Jetons
Considérons un exemple pratique : la surveillance des transferts de jetons dans un simple contrat de jeton ERC-20.
La norme ERC-20 inclut un événement `Transfer` qui est émis chaque fois que des jetons sont transférés entre des comptes. Cet événement inclut l'adresse de l'expéditeur, l'adresse du destinataire et le montant transféré.
Voici comment vous pouvez écouter les événements `Transfer` dans votre application frontend :
Avec Web3.js :
myContract.events.Transfer({
fromBlock: 'latest'
}, function(error, event){
if(!error)
{
console.log("Événement de Transfert :", event);
const from = event.returnValues.from;
const to = event.returnValues.to;
const value = event.returnValues.value;
// Mettre à jour l'UI ou effectuer d'autres actions
console.log(`Jetons transférés de ${from} à ${to} : ${value}`);
}
else
{console.error(error);}
});
Avec ethers.js :
myContract.on("Transfer", (from, to, value, event) => {
console.log("Événement de Transfert émis !");
console.log("De :", from);
console.log("À :", to);
console.log("Valeur :", value.toString()); // La valeur est un BigNumber dans ethers.js
console.log("Données de l'événement :", event);
// Mettre à jour l'UI ou effectuer d'autres actions
console.log(`Jetons transférés de ${from} à ${to} : ${value.toString()}`);
});
Cet extrait de code écoute les événements `Transfer` et affiche dans la console l'adresse de l'expéditeur, l'adresse du destinataire et le montant transféré. Vous pouvez ensuite utiliser ces informations pour mettre à jour l'interface utilisateur de votre application, afficher l'historique des transactions ou effectuer d'autres actions.
Conclusion
Les écouteurs d'événements de smart contract blockchain frontend sont un outil puissant pour créer des DApps réactives et en temps réel. En surveillant les événements émis par les smart contracts, vous pouvez fournir aux utilisateurs des informations à jour et améliorer l'expérience utilisateur globale. Ce guide a couvert les concepts fondamentaux, les outils et les techniques pour créer des écouteurs d'événements, ainsi que des sujets avancés tels que le filtrage des événements, la gestion des transactions annulées et l'utilisation des WebSockets pour les mises à jour en temps réel. En suivant les meilleures pratiques décrites dans ce guide, vous pouvez créer des écouteurs d'événements robustes et sécurisés qui amélioreront la fonctionnalité et l'expérience utilisateur de vos DApps.