paint-brush
Créez un générateur de reçus avec uniquement l'API Rootstock et la méthode RPCpar@ileolami
184 lectures

Créez un générateur de reçus avec uniquement l'API Rootstock et la méthode RPC

par Ileolami19m2024/12/01
Read on Terminal Reader

Trop long; Pour lire

Les reçus sont importants pour valider les transactions et fournir une preuve d'achat. Cet article vous montrera comment créer un générateur de reçus simple mais efficace à l'aide de l'API Rootstock et d'une seule méthode RPC (Remote Procedure Call).
featured image - Créez un générateur de reçus avec uniquement l'API Rootstock et la méthode RPC
Ileolami HackerNoon profile picture
0-item
1-item

Dans le monde d'aujourd'hui, les reçus sont essentiels pour valider les transactions et conserver la preuve des achats. Qu'il s'agisse d'une grande banque ou d'un petit magasin de bord de route, les reçus aident les entreprises et les particuliers à s'organiser et à suivre leurs dépenses.


Mais voilà le problème : la plupart des dApps ne fournissent pas de reçus et s'appuient sur des explorateurs pour vérifier les détails des transactions. Et si vous n'aviez pas à vous y fier ? Imaginez à quel point il serait plus pratique pour vos utilisateurs de générer des reçus directement, sans avoir à vérifier leurs portefeuilles.


Si vous créez une dApp basée sur le paiement sur Rootstock, cet article vous montrera comment créer un générateur de reçus simple mais efficace à l'aide de l'API Rootstock et d'une seule méthode RPC (Remote Procedure Call). Cette approche facilite le processus et garantit que vos enregistrements de transactions sont précis et faciles d'accès.


Apprenons les étapes et les outils nécessaires pour créer une expérience de génération de reçus fluide.


Prérequis

  1. Vous devez avoir un nœud installé sur votre appareil
  2. connaissances en Javascript
  3. Framework Js installé de votre choix
  4. Éditeur de code, par exemple VScode

J'utiliserai React Typescript et TailwindCSS pour le style

Outils et technologies

  1. Clé API de Rootstock
  2. Web3js : pour interagir avec RPC
  3. QRCode React : pour générer un QR code que les utilisateurs peuvent scanner et obtenir leur reçu
  4. Jspdf : pour générer le reçu en PDF

Installer, importer les packages et créer le composant fonctionnel

  1. Installez toutes les dépendances à l’aide de cette commande :

     npm i web3js jspdf qrcode.react
  2. Créez un nouveau fichier ou utilisez App.jsx

  3. Importez les packages dans le fichier avec les éléments suivants :

     import { useState } from "react"; import Web3 from "web3"; import { jsPDF } from "jspdf"; import { QRCodeSVG } from "qrcode.react";
  4. Initialiser le composant fonctionnel

     const TransactionReceipt = () => { /......./ } export default TransactionReceipt;


Gestion d'état et installation Web3

L'extrait de code ici gérera l'état et la fonctionnalité de récupération et d'affichage des détails de transaction à l'aide du hook useState, de Web3js, de Rootstock RPC et de l'API.

 const [transactionId, setTransactionId] = useState(""); interface TransactionDetails { transactionHash: string; from: string; to: string; cumulativeGasUsed: number; blockNumber: number; contractAddress?: string; } const [transactionDetails, setTransactionDetails] = useState<TransactionDetails | null>(null); const [error, setError] = useState(""); const web3 = new Web3( `https://rpc.testnet.rootstock.io/${import.meta.env.VITE_API_KEY}` );
  1. Gestion de l'État :

    • const [transactionId, setTransactionId] = useState(""); : Cette ligne initialise une variable d'état transactionId . Cette variable d'état sera responsable du hachage de transaction saisi que d'autres variables et fonctions exploiteront pour générer le reçu.
    • const [transactionDetails, setTransactionDetails] = useState<TransactionDetails | null>(null); : Cette ligne initialise une variable d'état transactionDetails avec une valeur null et fournit une fonction setTransactionDetails pour mettre à jour sa valeur. L'état peut contenir soit un objet TransactionDetails , soit null .
    • const [error, setError] = useState(""); : Cette ligne initialise une variable d'état error avec une chaîne vide et fournit une fonction setError pour mettre à jour sa valeur.
  2. Interface TypeScript :

    • interface TransactionDetails : cela définit une interface TypeScript pour la structure de l'objet de détails de transaction. Il comprend des propriétés telles que transactionHash , from , to , cumulativeGasUsed , blockNumber et une contractAddress facultative.
  3. Initialisation Web3 :

    • const web3 = new Web3(https://rpc.testnet.rootstock.io/${import.meta.env.VITE_API_KEY}); : Cette ligne initialise Web3js, en se connectant au point de terminaison RPC du réseau de test Rootstock. L'URL du point de terminaison inclut une clé API qui est récupérée à partir des variables d'environnement à l'aide de import.meta.env.VITE_API_KEY .


Fonction permettant de récupérer les détails de la transaction

Le code ici récupérera les détails de la transaction à l'aide d'une fonction asynchrone de Rootstock avec la méthode web3.js.

 const fetchTransactionDetails = async () => { try { setError(""); setTransactionDetails(null); const receipt = await web3.eth.getTransactionReceipt(transactionId); if (!receipt) { throw new Error("Transaction not found!"); } setTransactionDetails(receipt); } catch (err) { if (err instanceof Error) { setError(err.message); } else { setError("An unknown error occurred"); } } };
  1. Configuration de la gestion des erreurs :
    • try { ... } catch (err) { ... } : Cette structure est utilisée pour gérer les erreurs qui pourraient survenir lors de l'exécution de la fonction.
  2. Réinitialiser l'état :
    • setError("");: Ceci efface tous les messages d'erreur précédents en définissant l'état error sur une chaîne vide.
    • setTransactionDetails(null);: Cela efface tous les détails de transaction précédents en définissant l'état transactionDetails sur null .
  3. Récupérer le reçu de transaction :
    • const receipt = await web3.eth.getTransactionReceipt(transactionId) ;: Cette ligne utilise la méthode web3js pour récupérer le reçu de transaction pour le transactionId saisi.
  4. Vérification de réception :
    • if (!receipt) { throw new Error("Transaction not found!"); } : Si le reçu n'est pas trouvé (c'est-à-dire que le reçu est null ou undefined ), une erreur est générée avec le message "Transaction not found!".
  5. Définir les détails de la transaction :
    • setTransactionDetails(receipt) : Si le reçu est trouvé, il met à jour l'état transactionDetails avec le reçu récupéré.
  6. Gestion des erreurs :
    • catch (err) { ... } : Ce bloc intercepte toutes les erreurs qui se produisent pendant l'exécution du bloc try .
    • if (err instanceof Error) { setError(err.message); } else { setError("An unknown error occurred"); } : Si l'erreur détectée est une instance de la classe Error, elle définit l'état error sur le message d'erreur. Sinon, elle définit l'état error sur un message d'erreur générique "Une erreur inconnue s'est produite".


Fonctions pour générer un reçu PDF

Ici, le package Jspdf sera utilisé pour générer le PDF contenant les détails de la transaction.

 const generatePDF = () => { if (!transactionDetails) return; const { transactionHash, from, to, cumulativeGasUsed, blockNumber, contractAddress, } = transactionDetails; const pdf = new jsPDF(); pdf.setFontSize(16); pdf.text("Transaction Receipt", 10, 10); pdf.setFontSize(12); pdf.text(`Transaction Hash: ${transactionHash}`, 10, 20); pdf.text(`From: ${from}`, 10, 30); pdf.text(`Contract Address: ${contractAddress}`, 10, 40); pdf.text(`To: ${to}`, 10, 40); pdf.text(`Cumulative Gas Used: ${cumulativeGasUsed}`, 10, 50); pdf.text(`Block Number: ${blockNumber}`, 10, 60); pdf.save("Transaction_Receipt.pdf"); };
  1. Vérifiez les détails de la transaction :
    • if (!transactionDetails) return; : Ceci vérifie si transactionDetails est null ou undefined . Si c'est le cas, la fonction retourne plus tôt que prévu et ne fait rien.


  2. Détails de la transaction de déstructuration :
    • const { transactionHash, from, to, cumulativeGasUsed, blockNumber, contractAddress } = transactionDetails; : Cela déstructure l'objet transactionDetails pour extraire les propriétés individuelles pour un accès plus facile.


  3. Créer un document PDF :
    • const pdf = new jsPDF() : Ceci crée une nouvelle instance de la classe jsPDF, qui représente un document PDF.


  4. Définir la taille de la police et ajouter un titre :
    • pdf.setFontSize(16) : Ceci définit la taille de police du titre sur 16.

    • pdf.text("Transaction Receipt", 10, 10); : Ceci ajoute le titre "Reçu de transaction" aux coordonnées (10, 10) dans le document PDF.


  5. Ajouter les détails de la transaction au PDF :
    • pdf.setFontSize(12); : Ceci définit la taille de la police à 12 pour le reste du texte.

    • pdf.text(Transaction Hash : ${transactionHash} , 10, 20); : Ceci ajoute le hachage de transaction aux coordonnées (10, 20).

    • pdf.text(From: ${from}, 10, 30); : Ceci ajoute l'adresse de l'expéditeur aux coordonnées (10, 30).

    • pdf.text(Contract Address: ${contractAddress}, 10, 40); : Ceci ajoute l'adresse du contrat aux coordonnées (10, 40). Remarque : cette ligne doit être corrigée pour éviter tout chevauchement de texte.

    • pdf.text(To: ${to}, 10, 50); : Ceci ajoute l'adresse du destinataire aux coordonnées (10, 50).

    • pdf.text(Gaz cumulé utilisé : ${cumulativeGasUsed} , 10, 60); : Ceci ajoute le gaz cumulé utilisé aux coordonnées (10, 60).

    • pdf.text(Block Number: ${blockNumber}, 10, 70); : Ceci ajoute le numéro de bloc aux coordonnées (10, 70).


  6. Enregistrer le document PDF :
    • pdf.save("Transaction_Receipt.pdf");: Cela enregistrera le document PDF avec le nom de fichier "Transaction_Receipt.pdf".

L'interface utilisateur

Ici, vous restituerez ces composants fonctionnels sous forme d'interface utilisateur aux utilisateurs.

Ce code a déjà inclus le style à l'aide de Tailwindcss

 return ( <div className="p-8 font-sans bg-gray-100 min-h-screen"> <div className="max-w-3xl m-auto bg-white p-6 rounded-lg shadow-lg"> <h1 className="text-3xl font-bold mb-6 text-center text-blue-600"> Transaction Receipt Generator </h1> <div className="mb-6"> <div className="flex"> <input type="text" id="transactionId" value={transactionId} onChange={(e) => setTransactionId(e.target.value)} placeholder="Enter transaction hash" className="border p-2 w-full rounded-l-lg" /> <button onClick={fetchTransactionDetails} className="p-2 bg-blue-500 text-white rounded-r-lg" > Fetch Details </button> </div> </div> {error && ( <p className="text-red-500 mt-4 text-center">Error: {error}</p> )} {transactionDetails && ( <div className="mt-6 flex flex-row gap-8"> <div className="w-2/3"> <h2 className="text-2xl font-semibold mb-4 text-center"> Transaction Details </h2> <div className="bg-gray-50 p-4 rounded-lg shadow-inner w-[460px]"> <p> <strong>Transaction Hash:</strong>{" "} {`${transactionDetails.transactionHash.slice( 0, 6 )}...${transactionDetails.transactionHash.slice(-6)}`} </p> <p> <strong>From:</strong> {transactionDetails.from} </p> <p> <strong>Contract Address:</strong>{" "} {transactionDetails.contractAddress} </p> <p> <strong>To:</strong> {transactionDetails.to} </p> <p> <strong>Cumulative Gas Used:</strong>{" "} {transactionDetails.cumulativeGasUsed.toString()} </p> <p> <strong>Block Number:</strong>{" "} {transactionDetails.blockNumber.toString()} </p> </div> <button onClick={generatePDF} className="mt-6 w-full p-3 bg-green-500 text-white rounded-lg" > Download PDF Receipt </button> </div> <div className="w-1/2 text-center"> <h3 className="text-xl font-semibold mb-4">QR Code</h3> <QRCodeSVG value={`Transaction Hash: ${ transactionDetails.transactionHash }, From: ${transactionDetails.from}, To: ${transactionDetails.to}, Contract Address: ${transactionDetails.contractAddress}, Cumulative Gas Used: ${transactionDetails.cumulativeGasUsed.toString()}, Block Number: ${transactionDetails.blockNumber.toString()}`} size={200} className="mx-auto" /> </div> </div> )} </div> </div>

Pour le générateur de code QR, la bibliothèque qrcode.react a été utilisée et les détails de la transaction ont été cryptés dans le code QR SVG.

Base de code finale et sortie

Si vous suivez les étapes, votre base de code devrait ressembler à ceci :

 import { useState } from "react"; import Web3 from "web3"; import { jsPDF } from "jspdf"; import { QRCodeSVG } from "qrcode.react"; const TransactionReceipt = () => { const [transactionId, setTransactionId] = useState(""); interface TransactionDetails { transactionHash: string; from: string; to: string; cumulativeGasUsed: number; blockNumber: number; contractAddress?: string; } const [transactionDetails, setTransactionDetails] = useState<TransactionDetails | null>(null); const [error, setError] = useState(""); const web3 = new Web3( `https://rpc.testnet.rootstock.io/${import.meta.env.VITE_API_KEY}` ); const fetchTransactionDetails = async () => { try { setError(""); setTransactionDetails(null); const receipt = await web3.eth.getTransactionReceipt(transactionId); if (!receipt) { throw new Error("Transaction not found!"); } setTransactionDetails(receipt); } catch (err) { if (err instanceof Error) { setError(err.message); } else { setError("An unknown error occurred"); } } }; const generatePDF = () => { if (!transactionDetails) return; const { transactionHash, from, to, cumulativeGasUsed, blockNumber, contractAddress, } = transactionDetails; const pdf = new jsPDF(); pdf.setFontSize(16); pdf.text("Transaction Receipt", 10, 10); pdf.setFontSize(12); pdf.text(`Transaction Hash: ${transactionHash}`, 10, 20); pdf.text(`From: ${from}`, 10, 30); pdf.text(`Contract Address: ${contractAddress}`, 10, 40); pdf.text(`To: ${to}`, 10, 40); pdf.text(`Cumulative Gas Used: ${cumulativeGasUsed}`, 10, 50); pdf.text(`Block Number: ${blockNumber}`, 10, 60); pdf.save("Transaction_Receipt.pdf"); }; return ( <div className="p-8 font-sans bg-gray-100 min-h-screen"> <div className="max-w-3xl m-auto bg-white p-6 rounded-lg shadow-lg"> <h1 className="text-3xl font-bold mb-6 text-center text-blue-600"> Transaction Receipt Generator </h1> <div className="mb-6"> <div className="flex"> <input type="text" id="transactionId" value={transactionId} onChange={(e) => setTransactionId(e.target.value)} placeholder="Enter transaction hash" className="border p-2 w-full rounded-l-lg" /> <button onClick={fetchTransactionDetails} className="p-2 bg-blue-500 text-white rounded-r-lg" > Fetch Details </button> </div> </div> {error && ( <p className="text-red-500 mt-4 text-center">Error: {error}</p> )} {transactionDetails && ( <div className="mt-6 flex flex-row gap-8"> <div className="w-2/3"> <h2 className="text-2xl font-semibold mb-4 text-center"> Transaction Details </h2> <div className="bg-gray-50 p-4 rounded-lg shadow-inner w-[460px]"> <p> <strong>Transaction Hash:</strong>{" "} {`${transactionDetails.transactionHash.slice( 0, 6 )}...${transactionDetails.transactionHash.slice(-6)}`} </p> <p> <strong>From:</strong> {transactionDetails.from} </p> <p> <strong>Contract Address:</strong>{" "} {transactionDetails.contractAddress} </p> <p> <strong>To:</strong> {transactionDetails.to} </p> <p> <strong>Cumulative Gas Used:</strong>{" "} {transactionDetails.cumulativeGasUsed.toString()} </p> <p> <strong>Block Number:</strong>{" "} {transactionDetails.blockNumber.toString()} </p> </div> <button onClick={generatePDF} className="mt-6 w-full p-3 bg-green-500 text-white rounded-lg" > Download PDF Receipt </button> </div> <div className="w-1/2 text-center"> <h3 className="text-xl font-semibold mb-4">QR Code</h3> <QRCodeSVG value={`Transaction Hash: ${ transactionDetails.transactionHash }, From: ${transactionDetails.from}, To: ${transactionDetails.to}, Contract Address: ${transactionDetails.contractAddress}, Cumulative Gas Used: ${transactionDetails.cumulativeGasUsed.toString()}, Block Number: ${transactionDetails.blockNumber.toString()}`} size={200} className="mx-auto" /> </div> </div> )} </div> </div> ); }; export default TransactionReceipt;


Ensuite, importez le TransactionReceipt et restituez-le dans votre fichier App.tsx

Démo

Conclusion

Dans cet article, vous avez pu créer un générateur de reçus dans un code PDF ou QR à l'aide de la clé API Rootstock et de la méthode RPC. J'espère donc voir cette fonctionnalité intégrée dans votre prochain projet d'application décentralisée.