Дар ҷаҳони имрӯза квитансияҳо барои тасдиқи транзаксияҳо ва нигоҳ доштани далели харидҳо муҳиманд. Новобаста аз он ки ин бонки калон ё дӯкони хурди канори роҳ аст, квитансияҳо ба корхонаҳо ва шахсони алоҳида кӯмак мекунанд, ки муташаккил бошанд ва хароҷоти онҳоро пайгирӣ кунанд.
Аммо ин аст, ки аксари dApps квитансия намедиҳанд ва барои тафтиши тафсилоти транзаксия ба муҳаққиқон такя мекунанд. Чӣ мешавад, агар шумо набояд ба он такя кунед? Тасаввур кунед, ки барои корбарони шумо бидуни тафтиши ҳамёнҳои худ мустақиман квитансия тавлид кардан то чӣ андоза қулайтар хоҳад буд.
Агар шумо дар асоси пардохт dApp дар Rootstock сохта истода бошед, ин мақола ба шумо нишон медиҳад, ки чӣ гуна як генератори содда ва самараноки квитансияро бо истифода аз Rootstock API ва танҳо як усули RPC (Занги дурдаст) эҷод кунед. Ин равиш равандро осонтар мекунад ва кафолат медиҳад, ки сабтҳои транзаксияҳои шумо дақиқ ва дастрас бошанд.
Биёед қадамҳо ва асбобҳоеро омӯзем, ки барои эҷоди таҷрибаи ҳамвор тавлид кардани квитансия лозиманд.
Шартҳои пешакӣ
- Шумо бояд гиреҳро дар дастгоҳи худ насб карда бошед
- дониш дар Javascript
- Чаҳорчӯбаи Js-и интихобкардаи шумо насб карда шудааст
- Муҳаррири код, масалан, VScode
Ман барои ороиши React Typescript ва TailwindCSS истифода хоҳам кард
Асбоб ва технологияҳо
- Калиди API Rootstock
- Web3js : барои ҳамкорӣ бо RPC
- QRCode React : барои тавлиди рамзи QR барои корбарон барои скан кардан ва гирифтани квитансия
- Jspdf : барои тавлиди квитансия дар PDF
Бастаҳоро насб кунед, ворид кунед ва ҷузъи функсионалӣ эҷод кунед
Бо истифода аз ин фармон ҳамаи вобастагиҳоро насб кунед:
npm i web3js jspdf qrcode.react
Файли нав эҷод кунед ё
App.jsx
ро истифода баредБастаҳоро ба файл бо зерин ворид кунед:
import { useState } from "react"; import Web3 from "web3"; import { jsPDF } from "jspdf"; import { QRCodeSVG } from "qrcode.react";
Ҷузъи функсионалӣ оғоз кунед
const TransactionReceipt = () => { /......./ } export default TransactionReceipt;
Идоракунии давлатӣ ва Web3 Intilaiztion
Парчами рамз дар ин ҷо ҳолат ва функсияҳоро барои гирифтан ва намоиш додани тафсилоти транзаксия бо истифодаи hook, Web3js, Rootstock RPC ва 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}` );
Идоракунии давлатӣ :
-
const [transactionId, setTransactionId] = useState("");
: Ин сатр тағирёбандаи ҳолатиtransactionId
оғоз мекунад. Ин тағирёбандаи ҳолат барои хэши муомилоти воридшуда масъул хоҳад буд, ки дигар тағирёбандаҳо ва функсияҳо барои тавлиди квитансия истифода хоҳанд кард. -
const [transactionDetails, setTransactionDetails] = useState<TransactionDetails | null>(null);
: Ин сатр тағирёбандаи ҳолатиtransactionDetails
бо арзишиnull
оғоз мекунад ва функсияиsetTransactionDetails
ро барои навсозии арзиши он таъмин мекунад. Ҳолат метавонад ё объектиTransactionDetails
ёnull
дошта бошад. -
const [error, setError] = useState("");
: Ин сатрerror
тағирёбандаи ҳолатиро бо сатри холӣ оғоз мекунад ва функсияиsetError
ро барои навсозии арзиши он таъмин мекунад.
-
Интерфейси TypeScript :
-
interface TransactionDetails
: Ин интерфейси TypeScript-ро барои сохтори объекти тафсилоти транзаксия муайян мекунад. Он дорои хосиятҳо ба монандиtransactionHash
,from
,to
,cumulativeGasUsed
,blockNumber
ваcontractAddress
ихтиёрӣ мебошад.
-
Оғозсозии Web3 :
-
const web3 = new Web3(https://rpc.testnet.rootstock.io/${import.meta.env.VITE_API_KEY});
: Ин сатр Web3js-ро оғоз мекунад, ки ба нуқтаи ниҳоии RPC ба testnet Rootstock пайваст мешавад. URL-и ниҳоӣ калиди API-ро дар бар мегирад, ки аз тағирёбандаҳои муҳити зист бо истифода азimport.meta.env.VITE_API_KEY
гирифта мешавад.
-
Функсия барои гирифтани тафсилоти транзаксия
Рамзи ин ҷо тафсилоти транзаксияро бо истифода аз функсияи асинхронӣ аз Rootstock бо усули 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"); } } };
- Танзими коркарди хато :
-
try { ... } catch (err) { ... }
: Ин сохтор барои коркарди ҳама гуна хатогиҳое, ки ҳангоми иҷрои функсия рух дода метавонанд, истифода мешавад.
-
- Ҳолати барқароркунӣ :
- setError("");: Ин ҳама гуна паёмҳои хатогии қаблиро бо гузоштани ҳолати
error
ба сатри холӣ тоза мекунад. - setTransactionDetails(null);: Ин ҳама тафсилоти муомилоти қаблиро бо гузоштани ҳолати
transactionDetails
баnull
тоза мекунад.
- setError("");: Ин ҳама гуна паёмҳои хатогии қаблиро бо гузоштани ҳолати
- Квитансияи транзаксия :
-
const receipt = await web3.eth.getTransactionReceipt(transactionId)
;: Ин сатр усули web3js-ро барои гирифтани квитансияи транзаксия барои транзакцияи воридшуда истифода мебарад.
-
- Санҷед, ки квитансия :
-
if (!receipt) { throw new Error("Transaction not found!"); }
: Агар квитансия ёфт нашавад (яъне квитансияnull
ёundefined
аст), хато бо паёми "Транзаксия ёфт нашуд!".
-
- Муайян кардани тафсилоти транзаксия :
-
setTransactionDetails(receipt)
: Агар квитансия ёфт шавад, он ҳолатиtransactionDetails
бо квитансияи гирифташуда нав мекунад.
-
- Муносибати хатогӣ :
-
catch (err) { ... }
: Ин блок ҳама гуна хатогиҳоеро, ки ҳангоми иҷрои блокиtry
рух медиҳанд, сабт мекунад. -
if (err instanceof Error) { setError(err.message); } else { setError("An unknown error occurred"); }
: Агар хатои дастгиршуда намунаи синфи Error бошад, он ҳолатиerror
ба паёми хато муқаррар мекунад. Дар акси ҳол, он ҳолатиerror
ба паёми хатогии умумӣ муқаррар мекунад "Хатогии номаълум рух дод".
-
Функсияҳо барои тавлиди квитансияи PDF
Дар ин ҷо бастаи Jspdf барои тавлиди PDF бо тафсилоти транзаксия истифода мешавад.
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"); };
- Тафсилоти транзаксияро тафтиш кунед :
if (!transactionDetails) return;
: Ин тафтиш мекунад, киtransactionDetails
null
ёundefined
аст. Агар ин тавр бошад, функсия барвақт бармегардад ва ҳеҷ кор намекунад.
- Тафсилоти амалиёти вайронкунӣ :
const { transactionHash, from, to, cumulativeGasUsed, blockNumber, contractAddress } = transactionDetails;
: Ин объектиtransactionDetails
ро вайрон мекунад, то хосиятҳои инфиродӣ барои дастрасии осонро истихроҷ кунад.
- Эҷоди ҳуҷҷати PDF :
const pdf = new jsPDF()
: Ин як мисоли нави синфи jsPDF-ро эҷод мекунад, ки ҳуҷҷати PDF-ро муаррифӣ мекунад.
- Андозаи шрифтро танзим кунед ва унвон илова кунед :
pdf.setFontSize(16)
: Ин андозаи ҳуруфи сарлавҳаро ба 16 муқаррар мекунад.pdf.text("Transaction Receipt", 10, 10);
: Ин дар координатҳо (10, 10) дар ҳуҷҷати PDF унвони "Квитансияи транзаксия" -ро илова мекунад.
- Илова кардани тафсилоти транзаксия ба PDF :
pdf.setFontSize(12);
: Ин андозаи шрифтро барои қисми боқимондаи матн ба 12 муқаррар мекунад.pdf.text(Transaction Hash
: ${transactionHash}, 10, 20);
: Ин ҳеши транзаксияро дар координатҳо (10, 20) илова мекунад.pdf.text(From: ${from}, 10, 30);
: Ин суроғаи ирсолкунандаро дар координатҳо (10, 30) илова мекунад.pdf.text(Contract Address: ${contractAddress}, 10, 40);
: Ин суроғаи шартномаро дар координатҳо (10, 40) илова мекунад. Эзоҳ: Ин сатр бояд ислоҳ карда шавад, то матн такрор нашавад.pdf.text(To: ${to}, 10, 50);
: Ин суроғаи қабулкунандаро дар координатҳо (10, 50) илова мекунад.pdf.text(Гази истифодашуда: ${кумилятивии гази истифодашуда}
, 10, 60);
: Ин гази ҷамъшавандаро, ки дар координатҳо (10, 60) истифода мешавад, илова мекунад.pdf.text(Block Number: ${blockNumber}, 10, 70);
: Ин рақами блокро дар координатҳо (10, 70) илова мекунад.
- Ҳуҷҷати PDF-ро захира кунед :
- pdf.save("Transaction_Receipt.pdf");: Ин ҳуҷҷати PDF-ро бо номи файли "Transaction_Receipt.pdf" захира мекунад.
Интерфейси корбар
Дар ин ҷо шумо он ҷузъҳои функсионалӣ ҳамчун UI ба корбарон пешкаш хоҳед кард.
Ин код аллакай услубро бо истифодаи 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>
Барои тавлидкунандаи рамзи QR, китобхонаи qrcode.react истифода шуд ва тафсилоти транзаксия дар он рамзи QR SVG рамзгузорӣ карда шуд.
Пойгоҳи коди ниҳоӣ ва натиҷа
Агар шумо ин қадамро иҷро кунед, пойгоҳи коди шумо бояд чунин бошад:
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;
Сипас, TransactionReceipt
-ро ворид кунед ва онро дар файли App.tsx
и худ гузоред
Намоиш
Хулоса
Дар ин мақола, шумо тавонистед як генератори квитансияро дар PDF ё QR бо истифода аз усули Rootstock API ва усули RPC созед. Ҳамин тавр, дар лоиҳаи навбатии dApp, ман умедворам, ки ин хусусиятро дар он бубинам.