Emhlabeni wanamuhla, amarisidi abalulekile ekuqinisekiseni okwenziwayo kanye nokugcina ubufakazi bokuthenga. Kungakhathaliseki ukuthi ibhange elikhulu noma isitolo esincane somgwaqo, amarisidi asiza amabhizinisi nabantu ngabanye ukuthi bahlale behlelekile futhi balandelele indlela abasebenzisa ngayo imali.
Kodwa nansi into: ama-dApps amaningi awanikezi amarisidi futhi athembele kubahloli ukuze baqinisekise imininingwane yokwenziwe. Kuthiwani uma bekungadingeki uthembele kulokho? Cabanga ukuthi kungaba lula kangakanani kubasebenzisi bakho ukwenza amarisidi ngokuqondile, ngaphandle kokudinga ukuhlola izikhwama zabo zemali.
Uma wakha i-dApp esekelwe enkokhelweni ku-Rootstock, lesi sihloko sizokukhombisa ukuthi ungayenza kanjani ijeneretha yamarisidi elula kodwa esebenzayo usebenzisa i-Rootstock API kanye nendlela eyodwa ye-RPC (I-Remote Procedure Call). Le ndlela yenza inqubo ibe lula futhi iqinisekisa ukuthi amarekhodi akho okwenziwayo anembile futhi kulula ukuwafinyelela.
Masifunde izinyathelo namathuluzi adingekayo ukuze udale umuzwa wokwenza amarisidi oshelelayo.
Okudingekayo
- Kufanele ufake i-node kudivayisi yakho
- ulwazi ku-Javascript
- Kufakwe uhlaka lwe-Js ozikhethele lona
- Isihleli Sekhodi isb, VScode
Ngizosebenzisa i-React Typescript ne-TailwindCSS ukwenza isitayela
Ithuluzi Nobuchwepheshe
- I-Rootstock API Key
- I-Web3js : ukusebenzisana ne-RPC
- I-QRCode React : ukwenza ikhodi ye-QR ukuze abasebenzisi bayiskene futhi bathole irisidi yabo
- Jspdf : ukwenza irisidi ibe ama-PDF
Faka, Ngenisa Amaphakheji bese Udala ingxenye esebenzayo
Faka konke okuncikile usebenzisa lo myalo :
npm i web3js jspdf qrcode.react
Dala ifayela elisha noma sebenzisa i
App.jsx
Ngenisa amaphakheji kufayela ngokulandelayo:
import { useState } from "react"; import Web3 from "web3"; import { jsPDF } from "jspdf"; import { QRCodeSVG } from "qrcode.react";
Qalisa ingxenye yokusebenza
const TransactionReceipt = () => { /......./ } export default TransactionReceipt;
I-State Management kanye ne-Web3 Intilaiztion
Amazwibela ekhodi lapha azophatha isimo kanye nokusebenza kokulanda nokubonisa imininingwane yokwenziwe kusetshenziswa i-useState hook, Web3js, Rootstock RPC kanye ne-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}` );
Ukuphathwa Kwezwe :
-
const [transactionId, setTransactionId] = useState("");
: Lo mugqa uqalisa itransactionId
eguquguqukayo yesimo . Lokhu okuguquguqukayo kwesimo kuzoba nesibopho se-hashi yokwenziwayo efakiwe lapho ezinye izinto eziguquguqukayo nemisebenzi izoba namandla ukuze kukhiqizwe irisidi. -
const [transactionDetails, setTransactionDetails] = useState<TransactionDetails | null>(null);
: Lo mugqa uqalisatransactionDetails
eguquguqukayo yesimo enenaninull
futhi inikeza umsebenzisetTransactionDetails
ukuze ubuyekeze inani layo. Isifunda singabamba into ethiTransactionDetails
nomanull
. -
const [error, setError] = useState("");
: Lo mugqa uqalisaerror
elishintshashintshayo lesimo ngochungechunge olungenalutho futhi uhlinzeka ngomsebenzisetError
ukuze ubuyekeze inani lalo.
-
I-TypeScript Interface :
-
interface TransactionDetails
: Lokhu kuchaza isixhumi esibonakalayo se-TypeScript sesakhiwo sento yemininingwane yokwenziwe. Kuhlanganisa izici ezifana netransactionHash
,from
,to
,cumulativeGasUsed
,blockNumber
, kanyecontractAddress
ozikhethela lona .
-
Ukuqaliswa kwe-Web3 :
-
const web3 = new Web3(https://rpc.testnet.rootstock.io/${import.meta.env.VITE_API_KEY});
: Lo mugqa uqalisa i-Web3js, ixhume endaweni yokugcina ye-RPC ku-Rootstock testnet. I-URL yephoyinti lokugcina ifaka phakathi ukhiye we-API otholwa kokuguquguqukayo kwemvelo kusetshenziswaimport.meta.env.VITE_API_KEY
.
-
Umsebenzi Wokulanda Imininingwane Yokwenziwe
Ikhodi lapha izolanda imininingwane yokwenziwayo isebenzisa umsebenzi ongavumelanisiwe ku-Rootstock ngendlela ye-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"); } } };
- Iphutha Lokuhlela :
-
try { ... } catch (err) { ... }
: Lesi sakhiwo sisetshenziselwa ukuphatha noma yimaphi amaphutha angenzeka ngesikhathi sokwenziwa komsebenzi.
-
- Setha kabusha isimo :
- setError("");: Lokhu kusula noma yimiphi imilayezo yephutha yangaphambilini ngokusetha isimo
error
kuyunithi yezinhlamvu engenalutho. - setTransactionDetails(null);: Lokhu kusula noma yimiphi imininingwane yokwenziwe yangaphambilini ngokusetha isimo
transactionDetails
ukuthinull
.
- setError("");: Lokhu kusula noma yimiphi imilayezo yephutha yangaphambilini ngokusetha isimo
- Landa irisidi yokwenziwe :
-
const receipt = await web3.eth.getTransactionReceipt(transactionId)
;: Lo mugqa usebenzisa indlela ye-web3js ukuze ulande irisidi yokwenziwe ye-Input TransactionId.
-
- Hlola Irisidi :
-
if (!receipt) { throw new Error("Transaction not found!"); }
: Uma irisidi ingatholakali (okungukuthi, irisidinull
nomaundefined
), ziphonswa iphutha ngomlayezo othi "Okwenziwe akutholakali!".
-
- Setha Imininingwane Yokwenziwe :
-
setTransactionDetails(receipt)
: Uma irisidi itholwa, ibuyekeza isimotransactionDetails
neresidi elandiwe.
-
- Ukuphatha Iphutha :
-
catch (err) { ... }
: Leli bhulokhi libamba noma yimaphi amaphutha enzeka ngesikhathi kusetshenziswa ibhulokhitry
. -
if (err instanceof Error) { setError(err.message); } else { setError("An unknown error occurred"); }
: Uma iphutha elibanjwe yisibonelo sekilasi Lephutha, lisetha isimoerror
kumlayezo wephutha. Uma kungenjalo, isetha isimoerror
kumlayezo wephutha elijwayelekile "Kwenzeke iphutha elingaziwa".
-
Imisebenzi Yokukhiqiza Irisidi ye-PDF
Lapha iphakheji ye-Jspdf izosetshenziselwa ukukhiqiza i-PDF equkethe imininingwane yokwenziwe.
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"); };
- Hlola imininingwane yokwenziwe :
if (!transactionDetails) return;
: Lokhu kuhlola ukuthitransactionDetails
null
nomaundefined
. Uma kunjalo, umsebenzi ubuya kusenesikhathi futhi awenzi lutho.
- Imininingwane Yokwenziwayo Kwesakhiwo :
const { transactionHash, from, to, cumulativeGasUsed, blockNumber, contractAddress } = transactionDetails;
: Lokhu kucekela phansi into yetransactionDetails
ukukhipha izakhiwo ngazinye ukuze zifinyeleleke kalula.
- Dala idokhumenti ye-PDF :
const pdf = new jsPDF()
: Lokhu kudala isibonelo esisha sekilasi le-jsPDF, elimele idokhumenti ye-PDF.
- Setha Usayizi Wefonti bese Wengeza Isihloko :
pdf.setFontSize(16)
: Lokhu kusetha usayizi wefonti wesihloko ku-16.pdf.text("Transaction Receipt", 10, 10);
: Lokhu kwengeza isihloko esithi "Irisidi Yokwenziwe" kumakhonsathi (10, 10) kudokhumenti ye-PDF.
- Engeza imininingwane yokwenziwe ku-PDF :
pdf.setFontSize(12);
: Lokhu kusetha usayizi wefonti ku-12 kuwo wonke umbhalo.pdf.text(Transaction Hash
: ${transactionHash}, 10, 20);
: Lokhu kungeza i-hashi yokwenziwayo kumazixhumanisi (10, 20).pdf.text(From: ${from}, 10, 30);
: Lokhu kwengeza ikheli lomthumeli kumazixhumanisi (10, 30).pdf.text(Contract Address: ${contractAddress}, 10, 40);
: Lokhu kwengeza ikheli lenkontileka kumazixhumanisi (10, 40). Qaphela: Lo mugqa kufanele ulungiswe ukugwema ukugqagqana kombhalo.pdf.text(To: ${to}, 10, 50);
: Lokhu kwengeza ikheli lomamukeli kumazixhumanisi (10, 50).pdf.text(I-Cumulative Gas Used: ${cumulativeGasUsed}
, 10, 60);
: Lokhu kungeza igesi eqoqwayo esetshenziswa ezididiyelweni (10, 60).pdf.text(Block Number: ${blockNumber}, 10, 70);
: Lokhu kwengeza inombolo yebhulokhi kuzixhumanisi (10, 70).
- Londoloza Idokhumenti ye-PDF :
- pdf.save("Transaction_Receipt.pdf");: Lokhu kuzolondoloza idokhumenti ye-PDF enegama lefayela elithi "Transaction_Receipt.pdf" .
Isixhumi esibonakalayo somsebenzisi
Lapha uzobe unikeza lezo zingxenye ezisebenzayo njenge-UI kubasebenzisi.
Le khodi isivele yafaka isitayela kusetshenziswa i-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>
Kujeneretha wekhodi ye-QR, kusetshenziswe umtapo wezincwadi we-qrcode.react, futhi imininingwane yokwenziwe yabethelwa kuyo ikhodi ye-QR SVG.
I-codebase yokugcina kanye nokuphumayo
Uma ulandela lesi sinyathelo, i-codebase yakho kufanele ibukeke kanje:
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;
Bese, ngenisa i- TransactionReceipt
futhi uyinikeze kufayela lakho le App.tsx
Idemo
Isiphetho
Kulesi sihloko, ukwazile ukwakha ijeneretha yamarisidi ibe yi-PDF noma ikhodi ye-QR usebenzisa i-Rootstock API Key kanye nendlela ye-RPC. Ngakho kuphrojekthi yakho elandelayo ye-dApp, ngithemba ukubona lesi sici kuyo.