Avy amin'ny fahatakarana ny antontam-teknolojia ho an'ny fampandrosoana Web3 DApp, dia tsy maintsy nianatra ny antontam-teknolojia fototra ho an'ny fivoaran'ny web3 dApp ianao, ny andraikitry ny RPC amin'ny fampivoarana dApp, ary ny fomba fampiasana dRPC hamoronana kaonty, mamorona fanalahidin'ny API, teboka farany, analyse endpoints. , ampio vola amin'ny kaontinao dRPC, ary jereo ny fifandanjanao.
Ny anjara asan'ny dRPC amin'ny fametrahana fifanarahana marani-tsaina dia ny fanatsorana ny fizotran'ny fananganana node Ethereum, izay manamora ny fifandraisan'ny mpamorona sy ny fametrahana azy amin'ny andalana kaody tokana.
Amin'ity lahatsoratra ity, hanoratra, hanangona, hizaha toetra ary hametraka fifanarahana marani-tsaina momba ny fandoavana kafe amin'ny Ethereum Sepolia Testnet ianao amin'ny fampiasana dRPC endpoint sy API key.
Ny endri-javatra dia ahitana:
Aleo holotoina ny tananao.
Mamorona lahatahiry iray eo ambanin'ny lahatahiry fakanao, ary omeo anarana hoe contracts
.
Mamorona rakitra eo ambanin'ny lahatahiry contracts
, ary omeo anarana hoe coffee.sol
.
hampiasa solidity ianao hanoratana ny fifanarahana marani-tsaina. Ny rakitra Solidity dia nomena anarana miaraka amin'ny fanitarana
.sol
satria io no fanitarana rakitra mahazatra ho an'ny kaody loharano Solidity.
Ampio ity kaody loharano manaraka ity amin'ny 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
: Ity famantarana ny fahazoan-dàlana ity dia manondro fa ny kaody dia nahazo alalana amin'ny alalan'ny Massachusetts Institute of Technology (MIT) License.
pragma solidity >=0.8.0 <0.9.0;
: Mamaritra fa nosoratana ho an'ny dikan-teny Solidity eo anelanelan'ny 0.8.0 (inclusive) sy 0.9.0 (exclusive) ny code. uint256 public constant coffeePrice = 0.0002 ether; uint256 public totalCoffeesSold; uint256 public totalEtherReceived;
coffeePrice
: Apetraka ho sanda tsy miova amin'ny 0.0002 ether
.totalCoffeesSold
: Manara-maso ny isan'ny kafe amidy.totalEtherReceived
: Manara-maso ny totalin'ny Etera voarain'ny fifanarahana.Ny hadisoana manokana ao amin'ny Solidity dia hafatra diso izay mifanaraka amin'ny tranga fampiasana manokana, fa tsy ny hafatra diso default izay omen'ny fiteny fandaharana . Afaka manampy amin'ny fanatsarana ny traikefan'ny mpampiasa izy ireo, ary afaka manampy amin'ny debugging sy fitazonana fifanarahana marani-tsaina ihany koa.
Mba hamaritana hadisoana mahazatra ao amin'ny Solidity dia azonao ampiasaina ity syntax manaraka ity:
error
: Ity teny fanalahidy ity dia ampiasaina hamaritana fahadisoana mahazatra error QuantityMustBeGreaterThanZero(); error InsufficientEtherSent(uint256 required, uint256 sent); error DirectEtherTransferNotAllowed();
QuantityMustBeGreaterThanZero()
: Miantoka fa mihoatra ny aotra ny isa.InsufficientEtherSent(uint256 required, uint256 sent)
: Miantoka fa ampy ny Etera nalefa.DirectEtherTransferNotAllowed()
: Manakana ny famindrana mivantana ny Etera amin'ny fifanarahana.Ny hetsika dia ampahany amin'ny fifanekena mitahiry ny tohan-kevitra nandalo tao amin'ny diarin'ny fifampiraharahana rehefa navoaka. Ny hetsika dia matetika ampiasaina hampahafantarana ny fampiharana fiantsoana momba ny toetry ny fifanarahana amin'izao fotoana izao amin'ny fampiasana ny endri-tsoratry ny EVM. Mampandre ny fampiharana izy ireo momba ny fanovana natao tamin'ny fifanarahana, izay azo ampiasaina hampandehanana ny lojika mifandraika amin'izany.
event CoffeePurchased(address indexed buyer, uint256 quantity, uint256 totalCost);
CoffeePurchased(address indexed buyer, uint256 quantity, uint256 totalCost)
: Fividianana kafe.Functions dia modules misy kaody tokana izay mahavita asa manokana. Esorin'izy ireo ny famerana ny fanoratana indray ny kaody mitovy. Fa kosa, ny devs dia afaka miantso asa ao amin'ny programa rehefa ilaina izany.
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
: Mitantana ny fividianana kafe ary manao ireto asa manaraka ireto:receive() external payable
: Mamerina mivantana ny famindrana Ether raha misy mandefa vola mivantana amin'ny adiresin'ny fifanarahana.getTotalCoffeesSold() external view returns (uint256)
: Mamerina ny fitambaran'ny kafe amidy.getTotalEtherReceived() external view returns (uint256)
: Mamerina ny totalin'ny Etera voaray.Eto ianao dia hampiasa Hardhat hanangonana ny fifanarahana marani-tsaina.
Mametraka Hardhat amin'ny fampiasana ity baiko manaraka ity.
npm install --save-dev hardhat
Hahazo ny valiny eto ambany ianao rehefa vita ny fametrahana.
Ao amin'ny lahatahiry iray izay anombohanao hardhat amin'ny fampiasana ity baiko baiko ity:
npx hardhat init
Mifidiana Create a Javascript project
amin'ny alàlan'ny fampiasana ny bokotra midina ary tsindrio ny Enter.
Tsindrio ny Enter raha hametraka ao amin'ny lahatahiry faka
Ekeo ny bitsika rehetra amin'ny fampiasana ny y
amin'ny fitendry anao ao anatin'izany ny fiankinan'ny @nomicfoundation/hardhat-toolbox
Hitanao ity valinteny eto ambany ity izay mampiseho fa nahomby ianao tamin'ny fanombohana
Ho hitanao fa misy lahatahiry sy rakitra vaovao nampidirina ao amin'ny tetikasanao. ohatra,
Lock.sol
,iginition/modules
,test/Lock.js
aryhardhat.config.cjs
. Aza manahy momba azy ireo.
Ny hany mahasoa dia ny
iginition/modules
syhardhat.config.cjs
. Ho fantatrao ny ampiasana azy ireny any aoriana any. Aza misalasala mamafaLock.sol
eo ambanin'ny fampirimanacontracts
syLock.js
eo ambanin'ny fampirimanaiginition/modules
.
Angony ny fifanarahana amin'ny fampiasana ity baiko manaraka ity:
npx hardhat compile
Coffee.json
dia ny kaody ABI amin'ny endrika JSON izay hiantsoanao rehefa mifandray amin'ny fifanarahana marani-tsaina. { "_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": {} }
Tena zava-dehibe sy tena ilaina ny manoratra sora-panadinana mandeha ho azy rehefa manorina ny fifanarahana marani-tsainao. Izy io dia miasa toy ny fanamarinana roa anton-javatra (2FA), miantoka fa ny fifanarahana marani-tsainao dia manatanteraka araka ny nantenaina alohan'ny handefasana azy amin'ny tambajotra mivantana.
Eo ambanin'ny lahatahiry test
dia mamorona rakitra vaovao, ary omeo anarana hoe Coffee.
cjs. Apetaho ao anatin'ilay rakitra ity kaody ity:
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"); }); }); });
Ity kaody ity dia mizaha toetra ny fiasan'ny fifanarahana smart Coffee. Tafiditra ao anatin'izany ny fitsapana amin'ny fametrahana, ny fividianana kafe ary ny fikarakarana ny famindrana mivantana amin'ny Ether amin'ny fifanarahana.
Ity misy fizarazarana:
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
sy totalEtherReceived
dia napetraka ho aotra aorian'ny fametrahana azy. 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
.totalCoffeesSold
sy totalEtherReceived
dia nohavaozina araka ny tokony ho izy taorian'ny fividianana. 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"); }); });
Rehefa avy nanoratra ny script fitsapana ianao dia :
console.log()
avy amin'ny kaody Solidity anao. Raha hampiasa izany ianao dia tsy maintsy manafatra hardhat/console.sol
amin'ny kaody fifanarahana toy izao: //SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "hardhat/console.sol"; contract Coffee { //... }
Mba hitsapana ny fifanarahana dia araho ity baiko manaraka ity ao amin'ny terminal anao:
npx hardhat test
Tokony hanana vokatra toy izao manaraka izao ianao:
Izany dia mampiseho fa miasa araka ny nantenaina ny fifanarahana marani-tsainao.
Raha mihazakazaka
npx hardhat test
ianao dia manangona ho azy ary andramo ny fifanarahana marani-tsaina. Azonao atao ny manandrana azy ary ampahafantaro ahy ao amin'ny sehatra fanehoan-kevitra.
Eto ianao dia hametraka ny fifanarahana hendry anao amin'ny Sepolia Testnet. Testnet dia ahafahanao mitsapa ny fifanarahana marani-tsainao amin'ny tontolo iray izay maka tahaka ny mainnet Ethereum nefa tsy mandany vola be. Raha tsara amin'ny fiasan'ny dApp ianao, dia azonao atao ny mamerina amin'ny Ethereum Mainnet.
Apetraho ny fonosana dotenv sy ireo fiankinana ireo.
npm install dotenv npm install --save-dev @nomicfoundation/hardhat-web3-v4 'web3@4'
Izany dia hanampy Web3.Js sy Dotenv amin'ny tetikasanao amin'ny fampidirana azy ao amin'ny lahatahiry 'node_modules'.
ampidiro ao amin'ny rakitra hardhat.config.cjs
izy ireo
require('dotenv').config(); require("@nomicfoundation/hardhat-toolbox"); require("@nomicfoundation/hardhat-web3-v4"); const HardhatUserConfig = require("hardhat/config"); module.exports = { solidity: "0.8.24", } };
Mamorona rakitra .env
ao amin'ny lahatahiry fakanao.
Raiso ny lakilen'ny kaontinao manokana avy amin'ny kitapom-bola MetaMask sy ny lakilen'ny dRPC API.
Tehirizo ao amin'ny rakitra .env
anao izy ireo .
DRPC_API_KEY=your_drpc_api_key PRIVATE_KEY=your_wallet_private_key
Havaozy ny rakitra hardhat.config.cjs
mba hampidirana ny 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}`], } } };
Mamorona rakitra script vaovao eo ambanin'ny fampirimana ignition/module
, ary omeo anarana hoe deploy.cjs
. Ampio ity kaody manaraka ity mba hametrahana ny fifanarahana marani-tsainao:
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules"); const CoffeeModule = buildModule("CoffeeModule", (m) => { const coffee = m.contract("Coffee"); return { coffee }; }); module.exports = CoffeeModule;
Ampidiro ny fifanarahana smart amin'ny alàlan'ny fampandehanana ity baiko manaraka ity ao amin'ny terminal anao:
npx hardhat ignition deploy ./ignition/modules/deploy.cjs --network sepolia
Aorian'ny fampandehanana ny baikon'ny baiko dia angatahina ianao Confirm deploy to network sepolia (11155111)? (y/n)
, soraty ny y
. Tokony ho hitanao ny adiresin'ny fifanarahana marani-tsaina napetrakao ao amin'ny terminal rehefa vita ny fametrahana.
Azonao atao ihany koa ny miditra amin'ny adiresin'ny fifanarahana ao amin'ny rakitra deployed_addresses.json
.
Arahabaina, nahomby tamin'ny fametrahanao ny fifanarahana hendry tamin'ny Sepolia Testnet ianao. 🎉
Ity lahatsoratra ity dia nampianatra anao ny fomba hanoratana fifanarahana marani-tsaina momba ny fandoavam-bola, fitsapana, fanangonana ary fametrahana fifanarahana marani-tsaina mampiasa ny hardhat CLI.
Ao amin'ny lahatsoratra manaraka dia hianatra ny hanangana ny faran'ny anoloana ho an'ity dApp ity ianao. Ity UI ity dia ahitana:
Mihoatra ny Hafatra Default: Mifehy ny fahadisoana mahazatra amin'ny Solidity
Inona no atao hoe Solidity Functions?