Kubva pakunzwisisa tech stack yeWeb3 DApp budiriro, unofanira kunge wakadzidza iyo yakakosha tech stack yewebhu3 dApp budiriro, basa reRPC mukuvandudza dApp, uye mashandisiro edRPC kugadzira account, kugadzira kiyi yeAPI, magumo, endpoints analytics. , wedzera mari kuAccount yako yedRPC, uye tarisa chiyero chako.
Basa reDRPC pakuisa zvibvumirano zvakanaka nderokurerutsa nzira yekumisikidza Ethereum node, zvichiita kuti zvive nyore kune vanogadzira kutaurirana uye kutumira nemutsara mumwe chete wekodhi.
Muchikamu chino, iwe uchanyora, kuunganidza, kuedza, uye kutumira kontrakiti yekubhadhara kofi kuEthereum Sepolia Testnet uchishandisa dRPC endpoint uye API key.
Zvinhu zvacho zvinosanganisira:
Ngatisvibise maoko enyu.
Gadzira Folder pasi pemidzi yako dhairekitori, uye itumidze iyo contracts
.
Gadzira Faira pasi pegwaro contracts
, woritumidza kuti coffee.sol
.
unenge uchishandisa kusimba kunyora smart kontrakiti. Mafaira eSolidity anopihwa mazita neiyo
.sol
extension nekuti ndiyo yakajairwa faira rekuwedzera yeSolidity source code.
Wedzera iyo inotevera sosi kodhi kune coffee.sol
:
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; contract Coffee { uint256 public constant coffeePrice = 0.0002 ether; uint256 public totalCoffeesSold; uint256 public totalEtherReceived; // Custom error definitions error QuantityMustBeGreaterThanZero(); error InsufficientEtherSent(uint256 required, uint256 sent); error DirectEtherTransferNotAllowed(); // Event to log coffee purchases event CoffeePurchased(address indexed buyer, uint256 quantity, uint256 totalCost); // Function to buy coffee function buyCoffee(uint256 quantity) external payable { if (quantity <= 0) { revert QuantityMustBeGreaterThanZero(); } uint256 totalCost = coffeePrice * quantity; if (msg.value > totalCost) { revert InsufficientEtherSent(totalCost, msg.value); } // Update the total coffees sold and total ether received totalCoffeesSold += quantity; totalEtherReceived += totalCost; console.log("Total ether received updated:", totalEtherReceived); console.log("Total coffee sold updated:", totalCoffeesSold); // Emit the purchase event emit CoffeePurchased(msg.sender, quantity, totalCost); // Refund excess Ether sent if (msg.value > totalCost) { uint256 refundAmount = msg.value - totalCost; payable(msg.sender).transfer(refundAmount); } } // Fallback function to handle Ether sent directly to the contract receive() external payable { revert DirectEtherTransferNotAllowed(); } // Public view functions to get totals function getTotalCoffeesSold() external view returns (uint256) { console.log("getTotalCoffeesSold :", totalCoffeesSold); return totalCoffeesSold; } function getTotalEtherReceived() external view returns (uint256) { console.log("getTotalEtherReceived :", totalEtherReceived); return totalEtherReceived; } }
//SPDX-License-Identifier: MIT
: Ichi chiziviso cherezinesi chinoratidza kuti kodhi inopihwa rezinesi pasi peMassachusetts Institute of Technology (MIT) License.
pragma solidity >=0.8.0 <0.9.0;
: Inotsanangura kuti kodhi yakanyorerwa Solidity shanduro pakati pe0.8.0 (inosanganisira) uye 0.9.0 (yakasarudzika). uint256 public constant coffeePrice = 0.0002 ether; uint256 public totalCoffeesSold; uint256 public totalEtherReceived;
coffeePrice
: Set as a constant value of 0.0002 ether
.totalCoffeesSold
: Inoteedzera huwandu hwekofi dzakatengeswa.totalEtherReceived
: Inotevedzera Eteri yose yakagamuchirwa nekondirakiti.Zvikanganiso zvechinyakare muSolidity mameseji ekukanganisa akagadzirirwa kune imwe nyaya yekushandisa, pane yekukanganisa mameseji anopihwa nemutauro wechirongwa . Vanogona kubatsira kuvandudza ruzivo rwemushandisi, uye zvakare vanogona kubatsira nekugadzirisa uye kuchengetedza smart zvibvumirano.
Kutsanangura kukanganisa kwetsika muSolidity, unogona kushandisa inotevera syntax:
error
: Iri izwi guru rinoshandiswa kutsanangura kukanganisa kwetsika error QuantityMustBeGreaterThanZero(); error InsufficientEtherSent(uint256 required, uint256 sent); error DirectEtherTransferNotAllowed();
QuantityMustBeGreaterThanZero()
: Inova nechokwadi chekuti huwandu hwakakura kupfuura zero.InsufficientEtherSent(uint256 required, uint256 sent)
: Inovimbisa kuti Ether yakatumirwa yakakwana.DirectEtherTransferNotAllowed()
: Inodzivirira zvakananga Ether kutamiswa kune kontrakiti.Chiitiko chikamu chekondirakiti inochengeta nharo dzinopfuudzwa mumagwaro ekutengeserana kana aburitswa. Zviitiko zvinowanzo shandiswa kuzivisa chikumbiro chekufona nezve mamiriro ekondirakiti ikozvino uchishandisa EVM yekutema matanda. Ivo vanozivisa zvikumbiro nezve shanduko dzakaitwa kune zvibvumirano, izvo zvinozogona kushandiswa kumhanyisa zvine hukama.
event CoffeePurchased(address indexed buyer, uint256 quantity, uint256 totalCost);
CoffeePurchased(address indexed buyer, uint256 quantity, uint256 totalCost)
: Logs kutenga kofi.Mabasa ndeega-contained modules ekodhi inoita rimwe basa. Ivo vanobvisa redundancy yekunyora zvakare chidimbu chimwe chekodhi. Pane kudaro, ma devs anogona kufonera basa muchirongwa kana zvichidikanwa.
function buyCoffee(uint256 quantity) external payable { if (quantity <= 0) { revert QuantityMustBeGreaterThanZero(); } uint256 totalCost = coffeePrice * quantity; if (msg.value > totalCost) { revert InsufficientEtherSent(totalCost, msg.value); } // Update the total coffees sold and total ether received totalCoffeesSold += quantity; totalEtherReceived += totalCost; console.log("Total ether received updated:", totalEtherReceived); console.log("Total coffee sold updated:", totalCoffeesSold); // Emit the purchase event emit CoffeePurchased(msg.sender, quantity, totalCost); // Refund excess Ether sent if (msg.value > totalCost) { uint256 refundAmount = msg.value - totalCost; payable(msg.sender).transfer(refundAmount); } } receive() external payable { revert DirectEtherTransferNotAllowed(); } function getTotalCoffeesSold() external view returns (uint256) { console.log("getTotalCoffeesSold :", totalCoffeesSold); return totalCoffeesSold; } function getTotalEtherReceived() external view returns (uint256) { console.log("getTotalEtherReceived :", totalEtherReceived); return totalEtherReceived; }
buyCoffee(uint256 quantity) external payable
: Inobata kutenga kofi uye inoita zvinotevera:receive() external payable
: Inodzosera yakananga Eteri kutamiswa kana mumwe munhu akatumira mari kukero yekondirakiti zvakananga.getTotalCoffeesSold() external view returns (uint256)
: Inodzosa iyo yakazara kofi yakatengeswa.getTotalEtherReceived() external view returns (uint256)
: Inodzorera Eteri yose yakagamuchirwa.Pano, iwe unenge uchishandisa Hardhat kuunganidza iyo smart kontrakiti.
Isa Hardhat uchishandisa inotevera yekuraira kukurumidza.
npm install --save-dev hardhat
Iwe uchawana mhinduro pazasi mushure mekubudirira kuisirwa.
Mune rimwe dhairekitori raunotanga hardhat uchishandisa iyi command prompt:
npx hardhat init
Sarudza Create a Javascript project
uchishandisa bhatani remuseve pasi uye wodzvanya enter.
Dzvanya enter kuti uise mumudziyo folda
Gamuchira zvese zvinokurudzirwa uchishandisa y
pane kiibhodhi yako kusanganisira iyo @nomicfoundation/hardhat-toolbox
dependencies.
Unoona mhinduro iyi pazasi ichiratidza kuti wabudirira kutanga
Iwe unozoona mamwe maforodha matsva uye mafaera akawedzerwa kupurojekiti yako. semuenzaniso,
Lock.sol
,iginition/modules
,test/Lock.js
uyehardhat.config.cjs
. Usanetseka pamusoro pavo.
Iyo chete inobatsira
iginition/modules
uyehardhat.config.cjs
. Iwe unozoziva izvo zvavanoshandiswa gare gare. Inzwa wakasununguka kudzimaLock.sol
pasi pezvibvumiranocontracts
uyeLock.js
pasiiginition/modules
folda.
Gadzira kontrakiti uchishandisa inotevera command prompt:
npx hardhat compile
Coffee.json
faira mune ABI kodhi muJSON fomati iyo yauchadaidza kana uchinge uchifambidzana nekontrakiti yakangwara. { "_format": "hh-sol-artifact-1", "contractName": "Coffee", "sourceName": "contracts/coffee.sol", "abi": [ { "inputs": [], "name": "DirectEtherTransferNotAllowed", "type": "error" }, { "inputs": [ { "internalType": "uint256", "name": "required", "type": "uint256" }, { "internalType": "uint256", "name": "sent", "type": "uint256" } ], "name": "InsufficientEtherSent", "type": "error" }, { "inputs": [], "name": "QuantityMustBeGreaterThanZero", "type": "error" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "buyer", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "quantity", "type": "uint256" }, { "indexed": false, "internalType": "uint256", "name": "totalCost", "type": "uint256" } ], "name": "CoffeePurchased", "type": "event" }, { "inputs": [ { "internalType": "uint256", "name": "quantity", "type": "uint256" } ], "name": "buyCoffee", "outputs": [], "stateMutability": "payable", "type": "function" }, { "inputs": [], "name": "coffeePrice", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getTotalCoffeesSold", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "getTotalEtherReceived", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "totalCoffeesSold", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "totalEtherReceived", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "stateMutability": "payable", "type": "receive" } ], "bytecode": "", "deployedBytecode": "", "linkReferences": {}, "deployedLinkReferences": {} }
Kunyora otomatiki bvunzo script uchivaka yako smart kontrakiti kwakakosha uye kunokurudzirwa zvakanyanya. Inoita senge mbiri-chinhu chechokwadi (2FA), kuve nechokwadi chekuti yako smart kontrakiti inoita sezvaitarisirwa usati waiendesa kune mhenyu network.
Pasi peiyo test
folda gadzira faira nyowani, woritumidza kuti Coffee.
cjs. Mukati mefaira, isa kodhi iyi pazasi:
const { loadFixture } = require("@nomicfoundation/hardhat-toolbox/network-helpers.js"); const { expect } = require("chai"); const pkg = require("hardhat"); const ABI = require('../artifacts/contracts/coffee.sol/Coffee.json'); const { web3 } = pkg; describe("Coffee Contract", function () { // Fixture to deploy the Coffee contract async function deployCoffeeFixture() { const coffeeContract = new web3.eth.Contract(ABI.abi); coffeeContract.handleRevert = true; const [deployer, buyer] = await web3.eth.getAccounts(); const rawContract = coffeeContract.deploy({ data: ABI.bytecode, }); // Estimate gas for the deployment const estimateGas = await rawContract.estimateGas({ from: deployer }); // Deploy the contract const coffee = await rawContract.send({ from: deployer, gas: estimateGas.toString(), gasPrice: "10000000000", }); console.log("Coffee contract deployed to: ", coffee.options.address); return { coffee, deployer, buyer, rawContract }; } describe("Deployment", function () { // Test to check initial values after deployment it("Should set the initial values correctly", async function () { const { coffee } = await loadFixture(deployCoffeeFixture); const totalCoffeesSold = await coffee.methods.totalCoffeesSold().call(); const totalEtherReceived = await coffee.methods.totalEtherReceived().call(); expect(totalCoffeesSold).to.equal("0"); expect(totalEtherReceived).to.equal("0"); }); }); describe("Buying Coffee", function () { // Test to check coffee purchase and event emission it("Should purchase coffee and emit an event", async function () { const { coffee, buyer } = await loadFixture(deployCoffeeFixture); const quantity = 3; const totalCost = web3.utils.toWei("0.0006", "ether"); // Buyer purchases coffee const receipt = await coffee.methods.buyCoffee(quantity).send({ from: buyer, value: totalCost }); // Check event const event = receipt.events.CoffeePurchased; expect(event).to.exist; expect(event.returnValues.buyer).to.equal(buyer); expect(event.returnValues.quantity).to.equal(String(quantity)); expect(event.returnValues.totalCost).to.equal(totalCost); }); // Test to check revert when quantity is zero it("Should revert if the quantity is zero", async function () { const { coffee, buyer } = await loadFixture(deployCoffeeFixture); expect( coffee.methods.buyCoffee(0).send({ from: buyer, value: web3.utils.toWei("0.0002", "ether") }) ).to.be.revertedWith("QuantityMustBeGreaterThanZero"); }); // Test to check if totalCoffeesSold and totalEtherReceived are updated correctly it("Should update totalCoffeesSold and totalEtherReceived correctly", async function () { const { coffee, buyer } = await loadFixture(deployCoffeeFixture); const quantity = 5; const totalCost = web3.utils.toWei("0.001", "ether"); await coffee.methods.buyCoffee(quantity).send({ from: buyer, value: totalCost }); const totalCoffeesSold = await coffee.methods.totalCoffeesSold().call(); const totalEtherReceived = await coffee.methods.totalEtherReceived().call(); expect(totalCoffeesSold).to.equal(String(quantity)); expect(totalEtherReceived).to.equal(totalCost); }); }); describe("Fallback function", function () { // Test to check revert when ether is sent directly to the contract it("Should revert if ether is sent directly to the contract", async function () { const { coffee, buyer } = await loadFixture(deployCoffeeFixture); expect( web3.eth.sendTransaction({ from: buyer, to: coffee.options.address, value: web3.utils.toWei("0.001", "ether"), }) ).to.be.revertedWith("DirectEtherTransferNotAllowed"); }); }); });
Kodhi iyi inoedza mashandiro ekontrakiti yeKofi smart. Inosanganisira miedzo yekutumirwa, kutenga kofi, uye kubata zvakananga Ether kuendeswa kune kontrakiti.
Heino kupatsanurwa:
deployCoffeeFixture
async function deployCoffeeFixture() { const coffeeContract = new web3.eth.Contract(ABI.abi); coffeeContract.handleRevert = true; const [deployer, buyer] = await web3.eth.getAccounts(); const rawContract = coffeeContract.deploy({ data: ABI.bytecode, }); const estimateGas = await rawContract.estimateGas({ from: deployer }); const coffee = await rawContract.send({ from: deployer, gas: estimateGas.toString(), gasPrice: "10000000000", }); console.log("Coffee contract deployed to: ", coffee.options.address); return { coffee, deployer, buyer, rawContract }; }
describe("Deployment", function () { it("Should set the initial values correctly", async function () { const { coffee } = await loadFixture(deployCoffeeFixture); const totalCoffeesSold = await coffee.methods.totalCoffeesSold().call(); const totalEtherReceived = await coffee.methods.totalEtherReceived().call(); expect(totalCoffeesSold).to.equal("0"); expect(totalEtherReceived).to.equal("0"); }); });
totalCoffeesSold
uye totalEtherReceived
yakaiswa kune zero mushure mekutumirwa. describe("Buying Coffee", function () { it("Should purchase coffee and emit an event", async function () { const { coffee, buyer } = await loadFixture(deployCoffeeFixture); const quantity = 3; const totalCost = web3.utils.toWei("0.0006", "ether"); const receipt = await coffee.methods.buyCoffee(quantity).send({ from: buyer, value: totalCost }); const event = receipt.events.CoffeePurchased; expect(event).to.exist; expect(event.returnValues.buyer).to.equal(buyer); expect(event.returnValues.quantity).to.equal(String(quantity)); expect(event.returnValues.totalCost).to.equal(totalCost); }); it("Should revert if the quantity is zero", async function () { const { coffee, buyer } = await loadFixture(deployCoffeeFixture); expect( coffee.methods.buyCoffee(0).send({ from: buyer, value: web3.utils.toWei("0.0002", "ether") }) ).to.be.revertedWith("QuantityMustBeGreaterThanZero"); }); it("Should update totalCoffeesSold and totalEtherReceived correctly", async function () { const { coffee, buyer } = await loadFixture(deployCoffeeFixture); const quantity = 5; const totalCost = web3.utils.toWei("0.001", "ether"); await coffee.methods.buyCoffee(quantity).send({ from: buyer, value: totalCost }); const totalCoffeesSold = await coffee.methods.totalCoffeesSold().call(); const totalEtherReceived = await coffee.methods.totalEtherReceived().call(); expect(totalCoffeesSold).to.equal(String(quantity)); expect(totalEtherReceived).to.equal(totalCost); }); });
CoffeePurchased
chiitiko.totalCoffeesSold
and totalEtherReceived
inovandudzwa nemazvo mushure mekutenga. describe("Fallback function", function () { it("Should revert if ether is sent directly to the contract", async function () { const { coffee, buyer } = await loadFixture(deployCoffeeFixture); expect( web3.eth.sendTransaction({ from: buyer, to: coffee.options.address, value: web3.utils.toWei("0.001", "ether"), }) ).to.be.revertedWith("DirectEtherTransferNotAllowed"); }); });
Mushure mekunyora bvunzo script, iwe ucha :
console.log()
kubva pane yako Solidity kodhi. Kuti uishandise, unofanirwa kuendesa kunze hardhat/console.sol
mune yako kontrakiti kodhi seizvi: //SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "hardhat/console.sol"; contract Coffee { //... }
Kuti uedze chibvumirano, mhanyisa unotevera kuraira mune yako terminal:
npx hardhat test
Iwe unofanirwa kuve nezvakabuda seizvi pazasi:
Izvi zvinoratidza kuti smart contract yako inoshanda nenzira yainotarisirwa.
Kana iwe uchimhanya
npx hardhat test
inozvibatanidza uye kuyedza chibvumirano chakangwara. Unogona kuzviedza uye ndizivise muchikamu chekutaura.
Pano, iwe unenge uchitumira yako smart kontrakiti kuSepolia Testnet. Testnet inokubvumira kuti uedze chibvumirano chako chakangwara munzvimbo inotevedzera Ethereum mainnet pasina kuisa mari yakakosha. Kana iwe wakanaka nebasa re dApp, unogona kuendesa zvakare kuEthereum Mainnet.
Isa iyo dotenv package uye izvi zvinoenderana.
npm install dotenv npm install --save-dev @nomicfoundation/hardhat-web3-v4 'web3@4'
Izvi zvichawedzera Web3.Js uye Dotenv kupurojekiti yako nekuisanganisira mu 'node_modules' forodha.
pinza iwo hardhat.config.cjs
faira rako
require('dotenv').config(); require("@nomicfoundation/hardhat-toolbox"); require("@nomicfoundation/hardhat-web3-v4"); const HardhatUserConfig = require("hardhat/config"); module.exports = { solidity: "0.8.24", } };
Gadzira .env
faira mumudziyo wako.
Tora account yako yakavanzika kiyi kubva kune yako MetaMask wallet uye dRPC API kiyi.
Zvichengete mufaira rako .env
.
DRPC_API_KEY=your_drpc_api_key PRIVATE_KEY=your_wallet_private_key
Gadziridza iyo hardhat.config.cjs
faira kuti ubatanidze iyo Sepolia Testnet Configuration:
require('dotenv').config(); require("@nomicfoundation/hardhat-toolbox"); require("@nomicfoundation/hardhat-web3-v4"); const HardhatUserConfig = require("hardhat/config"); const dRPC_API_KEY = process.env.VITE_dRPC_API_KEY; const PRIVATE_KEY = process.env.VITE_PRIVATE_KEY; module.exports = { solidity: "0.8.24", networks: { sepolia: { url: `https://lb.drpc.org/ogrpc?network=sepolia&dkey=${dRPC_API_KEY}`, accounts: [`0x${PRIVATE_KEY}`], } } };
Gadzira script faira idzva pasi ignition/module
forodha, woripa zita deploy.cjs
. Wedzera iyo inotevera kodhi kuti uendese yako smart kontrakiti:
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules"); const CoffeeModule = buildModule("CoffeeModule", (m) => { const coffee = m.contract("Coffee"); return { coffee }; }); module.exports = CoffeeModule;
Shandisa smart contract nekumhanyisa unotevera kuraira mune yako terminal:
npx hardhat ignition deploy ./ignition/modules/deploy.cjs --network sepolia
Mushure mekuita chirevo chekuraira, iwe uchakumbirwa Confirm deploy to network sepolia (11155111)? (y/n)
, nyora y
. Iwe unofanirwa kuona kero yekontrakiti yako yakatumirwa smart mune terminal paunobudirira kutumirwa.
Iwe unogona zvakare kuwana kero yekondirakiti mu deployed_addresses.json
faira.
Makorokoto, wabudirira kutumira yako smart kontrakiti kuSepolia Testnet. 🎉
Ichi chinyorwa chakakudzidzisa manyorerwo ekubhadhara smart kontrakiti, bvunzo, kuunganidza uye kutumira smart kontrakiti uchishandisa iyo hardhat CLI.
Muchinyorwa chinotevera, iwe uchadzidza kuvaka kumberi kweiyi dApp. Iyi UI ichave ne:
Beyond Default Messages: Kubata Tsika Zvikanganiso muSolidity
Mastering Tsika Mhosho muSolidity: Simudza Yako Smart Contracts Kupfuura Default Mharidzo
Chii chinonzi Solidity Functions?