paint-brush
Izgradite generator potvrda samo s Rootstock API-jem i RPC metodompo@ileolami
184 čitanja

Izgradite generator potvrda samo s Rootstock API-jem i RPC metodom

po Ileolami19m2024/12/01
Read on Terminal Reader

Predugo; Čitati

Računi su važni za potvrdu transakcija i pružanje dokaza o kupnji. Ovaj će vam članak pokazati kako izraditi jednostavan, ali učinkovit generator potvrda pomoću Rootstock API-ja i jedne metode RPC (Remote Procedure Call).
featured image - Izgradite generator potvrda samo s Rootstock API-jem i RPC metodom
Ileolami HackerNoon profile picture
0-item
1-item

U današnjem svijetu, računi su ključni za potvrđivanje transakcija i čuvanje dokaza o kupnji. Bilo da se radi o velikoj banci ili maloj trgovini uz cestu, računi pomažu tvrtkama i pojedincima da ostanu organizirani i prate svoju potrošnju.


Ali evo u čemu je stvar: većina dApp-ova ne daje potvrde i oslanja se na istraživače za provjeru pojedinosti o transakciji. Što ako se ne morate oslanjati na to? Zamislite koliko bi praktičnije bilo za vaše korisnike da generiraju račune izravno, bez potrebe da provjeravaju svoje novčanike.


Ako na Rootstocku gradite dApp temeljen na plaćanju, ovaj će vam članak pokazati kako stvoriti jednostavan, ali učinkovit generator računa pomoću Rootstock API-ja i samo jedne RPC (Remote Procedure Call) metode. Ovaj pristup olakšava proces i osigurava da su vaši zapisi o transakcijama točni i laki za pristup.


Naučimo korake i alate potrebne za stvaranje glatkog iskustva generiranja računa.


Preduvjeti

  1. Morate imati instaliran čvor na svom uređaju
  2. poznavanje Javascripta
  3. Instaliran Js framework po vašem izboru
  4. Uređivač koda, npr. VScode

Koristit ću React Typescript i TailwindCSS za stiliziranje

Alat i tehnologije

  1. API ključ podloge
  2. Web3js : za interakciju s RPC-om
  3. QRCode React : za generiranje QR koda koji korisnici mogu skenirati i dobiti račun
  4. Jspdf : za generiranje računa u PDF-ove

Instalirajte, uvezite pakete i izradite funkcionalnu komponentu

  1. Instalirajte sve ovisnosti pomoću ove naredbe:

     npm i web3js jspdf qrcode.react
  2. Napravite novu datoteku ili upotrijebite App.jsx

  3. Uvezite pakete u datoteku sa sljedećim:

     import { useState } from "react"; import Web3 from "web3"; import { jsPDF } from "jspdf"; import { QRCodeSVG } from "qrcode.react";
  4. Inicijalizirajte funkcionalnu komponentu

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


Upravljanje stanjem i Web3 Intilaizacija

Isječak koda koji se nalazi ovdje upravljat će stanjem i funkcionalnošću za dohvaćanje i prikazivanje detalja transakcije pomoću useState kuke, Web3js, Rootstock RPC i API-ja.

 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. Upravljanje državom :

    • const [transactionId, setTransactionId] = useState(""); : Ovaj redak inicijalizira varijablu stanja transactionId . Ova varijabla stanja bit će odgovorna za uneseni hash transakcije koji će druge varijable i funkcije iskoristiti za generiranje računa.
    • const [transactionDetails, setTransactionDetails] = useState<TransactionDetails | null>(null); : Ovaj redak inicijalizira varijablu stanja transactionDetails s null vrijednošću i pruža funkciju setTransactionDetails za ažuriranje njezine vrijednosti. Stanje može sadržavati objekt TransactionDetails ili null .
    • const [error, setError] = useState(""); : Ovaj redak inicijalizira error varijable stanja s praznim nizom i pruža funkciju setError za ažuriranje njezine vrijednosti.
  2. TypeScript sučelje :

    • interface TransactionDetails : Ovo definira TypeScript sučelje za strukturu objekta detalja transakcije. Uključuje svojstva kao što su transactionHash , from , to , cumulativeGasUsed , blockNumber i izbornu contractAddress .
  3. Web3 inicijalizacija :

    • const web3 = new Web3(https://rpc.testnet.rootstock.io/${import.meta.env.VITE_API_KEY}); : Ovaj redak inicijalizira Web3js, povezujući se s RPC krajnjom točkom na Rootstock testnet. URL krajnje točke uključuje API ključ koji se dohvaća iz varijabli okruženja pomoću import.meta.env.VITE_API_KEY .


Funkcija za dohvaćanje pojedinosti o transakciji

Kod ovdje će dohvatiti detalje transakcije pomoću asinkrone funkcije iz Rootstocka s metodom 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. Postavljanje rukovanja pogreškama :
    • try { ... } catch (err) { ... } : Ova se struktura koristi za rješavanje bilo kakvih pogrešaka koje se mogu pojaviti tijekom izvođenja funkcije.
  2. Ponovno stanje :
    • setError("");: Ovo briše sve prethodne poruke o pogrešci postavljanjem stanja error na prazan niz.
    • setTransactionDetails(null);: Ovo briše sve prethodne detalje transakcije postavljanjem stanja transactionDetails na null .
  3. Dohvati potvrdu o transakciji :
    • const receipt = await web3.eth.getTransactionReceipt(transactionId) ;: Ovaj redak koristi metodu web3js za dohvaćanje potvrde o transakciji za uneseni transakcijskiId.
  4. Provjeri primitak :
    • if (!receipt) { throw new Error("Transaction not found!"); } : Ako potvrda nije pronađena (tj. potvrda je null ili undefined ), pojavljuje se pogreška s porukom "Transakcija nije pronađena!".
  5. Postavite detalje transakcije :
    • setTransactionDetails(receipt) : Ako je potvrda pronađena, ažurira stanje transactionDetails s dohvaćenom potvrdom.
  6. Rješavanje grešaka :
    • catch (err) { ... } : Ovaj blok hvata sve pogreške koje se dogode tijekom izvođenja bloka try .
    • if (err instanceof Error) { setError(err.message); } else { setError("An unknown error occurred"); } : Ako je uhvaćena pogreška instanca klase Pogreška, ona postavlja stanje error na poruku o pogrešci. U suprotnom, postavlja stanje error na generičku poruku o pogrešci "Došlo je do nepoznate pogreške".


Funkcije za generiranje PDF-a računa

Ovdje će se paket Jspdf koristiti za generiranje PDF-a koji sadrži detalje transakcije.

 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. Provjerite pojedinosti transakcije :
    • if (!transactionDetails) return; : Ovim se provjerava je li transactionDetails null ili undefined . Ako jest, funkcija se rano vraća i ne radi ništa.


  2. Pojedinosti o transakciji uništenja :
    • const { transactionHash, from, to, cumulativeGasUsed, blockNumber, contractAddress } = transactionDetails; : Ovo destrukturira objekt transactionDetails kako bi se izdvojila pojedinačna svojstva radi lakšeg pristupa.


  3. Napravite PDF dokument :
    • const pdf = new jsPDF() : Ovo stvara novu instancu klase jsPDF, koja predstavlja PDF dokument.


  4. Postavite veličinu fonta i dodajte naslov :
    • pdf.setFontSize(16) : Ovo postavlja veličinu fonta naslova na 16.

    • pdf.text("Transaction Receipt", 10, 10); : Ovo dodaje naslov "Potvrda o transakciji" na koordinatama (10, 10) u PDF dokumentu.


  5. Dodavanje pojedinosti o transakciji u PDF :
    • pdf.setFontSize(12); : Ovo postavlja veličinu fonta na 12 za ostatak teksta.

    • pdf.text(Transaction Hash : ${transactionHash} , 10, 20); : Ovo dodaje hash transakcije na koordinate (10, 20).

    • pdf.text(From: ${from}, 10, 30); : Ovo dodaje adresu pošiljatelja na koordinate (10, 30).

    • pdf.text(Contract Address: ${contractAddress}, 10, 40); : Ovo dodaje adresu ugovora na koordinate (10, 40). Napomena: ovaj redak treba ispraviti kako bi se izbjeglo preklapanje teksta.

    • pdf.text(To: ${to}, 10, 50); : Ovo dodaje adresu primatelja na koordinate (10, 50).

    • pdf.text(Kumulativno iskorišteni plin: ${cumulativeGasUsed} , 10, 60); : Ovo dodaje kumulativni plin korišten na koordinatama (10, 60).

    • pdf.text(Block Number: ${blockNumber}, 10, 70); : Ovo dodaje broj bloka na koordinate (10, 70).


  6. Spremi PDF dokument :
    • pdf.save("Transaction_Receipt.pdf");: Ovo će spremiti PDF dokument s nazivom datoteke "Transaction_Receipt.pdf" .

Korisničko sučelje

Ovdje ćete korisnicima prikazati te funkcionalne komponente kao korisničko sučelje.

Ovaj kod već je uključio stil korištenjem Tailwindcss-a

 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>

Za generator QR koda korištena je biblioteka qrcode.react, a detalji transakcije šifrirani su u QR kod SVG.

Konačna baza koda i izlaz

Ako slijedite korak, vaša bi baza koda trebala izgledati ovako:

 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;


Zatim uvezite TransactionReceipt i renderirajte ga u svojoj datoteci App.tsx

Demo

Zaključak

U ovom ste članku uspjeli izgraditi generator računa u PDF ili QR kod pomoću Rootstock API ključa i RPC metode. Nadam se da ću u vašem sljedećem dApp projektu vidjeti ovu značajku.