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: 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. ama-dApps 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 : ukusebenzisana ne-RPC I-Web3js : ukwenza ikhodi ye-QR ukuze abasebenzisi bayiskene futhi bathole irisidi yabo I-QRCode React : ukwenza irisidi ibe ama-PDF Jspdf 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 : Lo mugqa uqalisa i eguquguqukayo yesimo . Lokhu okuguquguqukayo kwesimo kuzoba nesibopho se-hashi yokwenziwayo efakiwe lapho ezinye izinto eziguquguqukayo nemisebenzi izoba namandla ukuze kukhiqizwe irisidi. const [transactionId, setTransactionId] = useState(""); transactionId : Lo mugqa uqalisa eguquguqukayo yesimo enenani futhi inikeza umsebenzi ukuze ubuyekeze inani layo. Isifunda singabamba into ethi noma . const [transactionDetails, setTransactionDetails] = useState<TransactionDetails | null>(null); transactionDetails null setTransactionDetails TransactionDetails null : Lo mugqa uqalisa elishintshashintshayo lesimo ngochungechunge olungenalutho futhi uhlinzeka ngomsebenzi ukuze ubuyekeze inani lalo. const [error, setError] = useState(""); error setError : I-TypeScript Interface : Lokhu kuchaza isixhumi esibonakalayo se-TypeScript sesakhiwo sento yemininingwane yokwenziwe. Kuhlanganisa izici ezifana ne , , , , , kanye ozikhethela lona . interface TransactionDetails transactionHash from to cumulativeGasUsed blockNumber contractAddress : Ukuqaliswa kwe-Web3 : 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 kusetshenziswa . const web3 = new Web3(https://rpc.testnet.rootstock.io/${import.meta.env.VITE_API_KEY}); import.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 : Lesi sakhiwo sisetshenziselwa ukuphatha noma yimaphi amaphutha angenzeka ngesikhathi sokwenziwa komsebenzi. try { ... } catch (err) { ... } : Setha kabusha isimo setError("");: Lokhu kusula noma yimiphi imilayezo yephutha yangaphambilini ngokusetha isimo kuyunithi yezinhlamvu engenalutho. error setTransactionDetails(null);: Lokhu kusula noma yimiphi imininingwane yokwenziwe yangaphambilini ngokusetha isimo ukuthi . transactionDetails null : Landa irisidi yokwenziwe ;: Lo mugqa usebenzisa indlela ye-web3js ukuze ulande irisidi yokwenziwe ye-Input TransactionId. const receipt = await web3.eth.getTransactionReceipt(transactionId) : Hlola Irisidi : Uma irisidi ingatholakali (okungukuthi, irisidi noma ), ziphonswa iphutha ngomlayezo othi "Okwenziwe akutholakali!". if (!receipt) { throw new Error("Transaction not found!"); } null undefined : Setha Imininingwane Yokwenziwe : Uma irisidi itholwa, ibuyekeza isimo neresidi elandiwe. setTransactionDetails(receipt) transactionDetails : Ukuphatha Iphutha : Leli bhulokhi libamba noma yimaphi amaphutha enzeka ngesikhathi kusetshenziswa ibhulokhi . catch (err) { ... } try : Uma iphutha elibanjwe yisibonelo sekilasi Lephutha, lisetha isimo kumlayezo wephutha. Uma kungenjalo, isetha isimo kumlayezo wephutha elijwayelekile "Kwenzeke iphutha elingaziwa". if (err instanceof Error) { setError(err.message); } else { setError("An unknown error occurred"); } error error 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 : Lokhu kuhlola ukuthi noma . Uma kunjalo, umsebenzi ubuya kusenesikhathi futhi awenzi lutho. if (!transactionDetails) return; transactionDetails null undefined : Imininingwane Yokwenziwayo Kwesakhiwo : Lokhu kucekela phansi into ye ukukhipha izakhiwo ngazinye ukuze zifinyeleleke kalula. const { transactionHash, from, to, cumulativeGasUsed, blockNumber, contractAddress } = transactionDetails; transactionDetails : Dala idokhumenti ye-PDF : Lokhu kudala isibonelo esisha sekilasi le-jsPDF, elimele idokhumenti ye-PDF. const pdf = new jsPDF() : Setha Usayizi Wefonti bese Wengeza Isihloko : Lokhu kusetha usayizi wefonti wesihloko ku-16. pdf.setFontSize(16) : Lokhu kwengeza isihloko esithi "Irisidi Yokwenziwe" kumakhonsathi (10, 10) kudokhumenti ye-PDF. pdf.text("Transaction Receipt", 10, 10); : Engeza imininingwane yokwenziwe ku-PDF : Lokhu kusetha usayizi wefonti ku-12 kuwo wonke umbhalo. pdf.setFontSize(12); : ${transactionHash} : Lokhu kungeza i-hashi yokwenziwayo kumazixhumanisi (10, 20). pdf.text(Transaction Hash , 10, 20); : Lokhu kwengeza ikheli lomthumeli kumazixhumanisi (10, 30). pdf.text(From: ${from}, 10, 30); : Lokhu kwengeza ikheli lenkontileka kumazixhumanisi (10, 40). Qaphela: Lo mugqa kufanele ulungiswe ukugwema ukugqagqana kombhalo. pdf.text(Contract Address: ${contractAddress}, 10, 40); : Lokhu kwengeza ikheli lomamukeli kumazixhumanisi (10, 50). pdf.text(To: ${to}, 10, 50); pdf.text(I-Cumulative Gas Used: ${cumulativeGasUsed} : Lokhu kungeza igesi eqoqwayo esetshenziswa ezididiyelweni (10, 60). , 10, 60); : Lokhu kwengeza inombolo yebhulokhi kuzixhumanisi (10, 70). pdf.text(Block Number: ${blockNumber}, 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- futhi uyinikeze kufayela lakho le TransactionReceipt App.tsx Idemo https://youtu.be/Xwkl9pu8UiM?embedable=true 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.