መእተዊ ካብ ምርዳእ tech stack for Web3 DApp development ን web3 dApp development ዝኸውን core tech stack፣ ተራ RPC ኣብ dApp development፣ ከምኡ እውን dRPC ከመይ ጌርካ ኣካውንት ንምፍጣር፣ API key ንምፍጣር፣ endpoints፣ endpoints analytics ትጥቀም ተማሂርካ ክትከውን ኣለካ ፣ ኣብ dRPC ኣካውንትካ ገንዘብ ወስኽ፣ ሚዛንካ ድማ መርምር። ተራ dRPC ኣብ ምዝርጋሕ ስማርት ውዕላት ንመስርሕ ምድላው Ethereum node ምቕላል እዩ፣ እዚ ድማ ንደቨሎፐራት ብሓደ መስመር ኮድ ጥራይ ንኽራኸቡን ንኽዝርግሑን ቀሊል ይገብሮም። ኣብዚ ጽሑፍ እዚ፡ dRPC endpointን API keyን ተጠቒምካ፡ ናይ ቡን ክፍሊት ስማርት ውዕል ናብ Ethereum Sepolia Testnet ክትጽሕፍ፡ ከተዋህልል፡ ክትፍትኖን ከተዋፍርን ኢኻ። እቶም ባህርያት ድማ፤ ክፍሊት ንቡን ዋጋ ቡን ምግምጋም ምውሳድ ጠቕላላ ቁጽሪ ዝተሸጠ ቡንን ጠቕላላ ዝተገብረ መጠን ገንዘብን። ኣእዳውኩም ንረክስ። ቅድመ ኩነት ድሮ ንሕሳብኩም ብሴፖልያ ፋውሰት ምወላ። ዋለተ ይሃልኻ ንኣብነት ሜታማስክ። ኣዳላዊ ኮድ። ድሮ ዝኾነ ዝመረጽካዮ Js libraries ወይ frameworks (ንኣብነት React.js, Next.js ወዘተ) ተኺለካ። ዕትሮ ማይ። ዘድልዩ ቴክኖሎጂታትን መሳርሕታትን ጽንዓት። React.js Vite.js(Typescript) ብምጥቃም ሃርድሃት። Web3.js. ዶተንቭ. dRPC ኤፒኣይ መፍትሕን መወዳእታ ነጥቢን። ናይ ኣካውንትካ ናይ ብሕቲ መፍትሕ። ሜታማስክ ምጽሓፍ ናይ ቡን ክፍሊት ስማርት ውዕል ኣብ ትሕቲ ሱር ማህደርካ Folder ፍጠር፣ ዝብል ስም ድማ ስመዮ። contracts ኣብ ትሕቲ ዝብል ማህደር ፋይል ፍጠር፣ ዝብል ስም ድማ ስመዮ። contracts coffee.sol ነቲ ስማርት ውዕል ንምጽሓፍ solidity ክትጥቀም ኢኻ። ፋይላት ሶሊዲቲ ብ ኤክስቴንሽን ዝተሰየሙ ምኽንያቱ ንሶሊዲቲ ምንጪ ኮድ ስታንዳርድ ፋይል ኤክስቴንሽን ስለዝኾነ። .sol ኣብ እዚ ዝስዕብ ምንጪ ኮድ ወስኹሉ : 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 ማሳቹሰትስ ኢንስቲትዩት ቴክኖሎጂ (MIT) : እቲ ኮድ ኣብ መንጎ 0.8.0 (ሓዊሱ)ን 0.9.0ን (ፍሉይ)ን ንዝርከቡ ስሪት ሶሊዲቲ ከም ዝተጻሕፈ ይገልጽ። pragma solidity >=0.8.0 <0.9.0; ስቴት ተለዋዋጢ uint256 public constant coffeePrice = 0.0002 ether; uint256 public totalCoffeesSold; uint256 public totalEtherReceived; : ከም ቀዋሚ ዋጋ ኣቐምጥ ። coffeePrice 0.0002 ether : ብዝሒ ዝተሸጡ ቡናት ይከታተል። totalCoffeesSold : ብውዕል ዝተቐበሎ ጠቕላላ ኢተር ይከታተል። totalEtherReceived ብሕታዊ ጌጋታት ኣብ ሶሊዲቲ ዝርከቡ ብሕታዊ ጌጋታት እዮም። ንተመኩሮ ተጠቃሚ ንምምሕያሽ ክሕግዙ ይኽእሉ፣ ከምኡ’ውን ኣብ ምእራምን ምሕላውን ስማርት ውዕላት ክሕግዙ ይኽእሉ። ብቋንቋ ፕሮግራሚንግ ዝቐርቡ ነባሪ መልእኽትታት ጌጋ ዘይኮነስ፡ ንፍሉይ ኣጠቓቕማ ዝተመጣጠኑ ናይ ጌጋ መልእኽትታት ኣብ ሶሊዲቲ ብሕታዊ ጌጋ ንምግላጽ፡ ነዚ ዝስዕብ ስነ-ቓል ክትጥቀም ትኽእል ኢኻ፤ : እዚ ቁልፊ ቃል እዚ ንሓደ ብሕታዊ ጌጋ ንምግላጽ ይጥቀመሉ error ፍሉይ ስም፦ እቲ ጌጋ ፍሉይ ስም ክህልዎ ኣለዎ። መለክዒታት፦ ኣብቲ ናይ ጌጋ መልእኽቲ ፍሉይ ዝርዝራት ወይ መለክዒታት ከተእቱ እንተደሊኻ፡ ድሕሪ ስም ጌጋ ኣብ ሓጹር ክትውስኾም ትኽእል ኢኻ። error QuantityMustBeGreaterThanZero(); error InsufficientEtherSent(uint256 required, uint256 sent); error DirectEtherTransferNotAllowed(); : እቲ ብዝሒ ካብ ዜሮ ከም ዝዓቢ የረጋግጽ። QuantityMustBeGreaterThanZero() : እቲ ዝተላእከ ኢተር እኹል ምዃኑ የረጋግጽ። InsufficientEtherSent(uint256 required, uint256 sent) : ቀጥታዊ ምስግጋር ኢተር ናብ ውዕል ይኽልክል። DirectEtherTransferNotAllowed() ፍጻመታት ፍጻመ ሓደ ክፋል ናይቲ ውዕል ኮይኑ፡ ኣብ ዝፍኖሉ እዋን ኣብ መዝገብ ትራንዛክሽን ዝሓልፉ ሞጎተታት ዝዕቅብ እዩ። መብዛሕትኡ ግዜ ፍጻመታት ነቲ ዝድውለሉ መተግበሪ ብዛዕባ ህሉው ኩነታት ናይቲ ውዕል ንምሕባር ዝጥቀሙሉ ኮይኖም ናይቲ EVM ናይ ምዝገባ ባህሪ ተጠቒሞም እዮም። ብዛዕባ ኣብ ውዕላት ዝተገብረ ለውጢ ንኣፕሊኬሽናት የፍልጡ፣ ድሕሪኡ ድማ ተዛማዲ ስነ-መጐት ንምስራሕ ክጥቀሙሉ ይኽእሉ። event CoffeePurchased(address indexed buyer, uint256 quantity, uint256 totalCost); : ዕድጊ ቡን ይምዝግብ። CoffeePurchased(address indexed buyer, uint256 quantity, uint256 totalCost) ተግባራት ተመሳሳሊ ቁራጽ ኮድ ዳግማይ ምጽሓፍ ዝብል ትርፊ የወግዱ። ኣብ ክንድኡስ፡ devs ኣብቲ ፕሮግራም ንዘሎ ፋንክሽን ኣድላዪ ኣብ ዝኾነሉ እዋን ክጽውዑ ይኽእሉ። ተግባራት ንሓደ ፍሉይ ዕማም ዝፍጽሙ ርእሶም ዝኽእሉ ሞዱላት ኮድ እዮም። 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 እቲ ብዝሒ ቅኑዕ እንተኾይኑ ኣረጋግጽ። ጠቕላላ ወጻኢታት ይሕሰብ። እኹል ኢተር ከም ዝለኣኽ የረጋግጽ። ተለዋዋጢ ኩነታት የዘምኖም። ነቲ ናይ ዕድጊ ፍጻመ ይፍኖ። ልዕሊ ዓቐን ኢተር ይመልስ። : ሓደ ሰብ ብቐጥታ ናብቲ ናይ ውዕል ኣድራሻ ገንዘብ እንተሰዲዱ ቀጥታዊ ናይ ኢተር ዝውውር ይመልስ። receive() external payable : ጠቕላላ ዝተሸጡ ቡናት ይመልስ። getTotalCoffeesSold() external view returns (uint256) : ጠቕላላ ዝተቐበለ ኢተር ይመልስ። getTotalEtherReceived() external view returns (uint256) ምጥርናፍ ናይ ቡን ክፍሊት ስማርት ውዕል ኣብዚ፡ ነቲ ስማርት ውዕል ንምጥርናፍ ሃርድሃት ክትጥቀሙ ኢኹም። ነዚ ዝስዕብ ትእዛዝ መመልከቲ ተጠቒምካ Hardhat ንጽዓኖ። npm install --save-dev hardhat ድሕሪ ዕዉት ምትካል እዚ ኣብ ታሕቲ ዘሎ መልሲ ክትረኽቡ ኢኹም። ኣብ ተመሳሳሊ ማህደር ነዚ ናይ ትእዛዝ ምልክት ተጠቂምካ hardhat ትጅምረሉ፤ npx hardhat init እሞ enter ንጽቀጥ። ነቲ ፍላጻ ንታሕቲ ዝብል ቁልፊ ብምጥቃም Create a Javascript project ምረጽ ኣብቲ ሱር ማህደር ንምትካል enter ንጽቀጥ ኩሎም ሓዊስካ ተቐበል ኣብ ቁልፊ ሰሌዳኻ y ብምጥቃም ዝቐርቡ ምልክታት @nomicfoundation/hardhat-toolbox ጽግዕተኛታት እዚ ኣብ ታሕቲ ዘሎ መልሲ ብዓወት ከም ዝጀመርካ ዘርኢ ትርእዮ ገለ ሓደስቲ ማህደርን ፋይላትን ኣብ ፕሮጀክትካ ከም ዝተወሰኹ ከተስተብህል ኢኻ። ንኣብነት Lock.sol ፡ iginition iginition/modules ፡ test test/Lock.js ከምኡ’ውን hardhat.config.cjs ። ብዛዕባኦም ኣይትጨነቑ። እዮም ። እቶም እንኮ ጠቐምቲ ድማ iginition/modules ን hardhat.config.cjs ። ንእንታይ ከም ዝውዕሉ ድሒርካ ክትፈልጥ ኢኻ። Lock.sol ኣብ ትሕቲ contracts folder ከምኡ ውን Lock.js ኣብ ትሕቲ iginition/modules folder ክትድምስሱ ናጻ ትኾኑ ነዚ ዝስዕብ ትእዛዝ ምልክት ተጠቒምካ ነቲ ውዕል ኣወሃህዶ፤ npx hardhat compile ከምዚኦም ዝኣመሰሉ ተወሳኺ ማህደርን ፋይላትን ትርኢ። ኣብ ውሽጢ Coffee.json ፋይል ብJSON ፎርማት ዘሎ ABI ኮድ ኣሎ ምስቲ ስማርት ውዕል ክትራኸብ ከለኻ ክትድውለሉ ኢኻ። { "_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": {} } ምፍታን ስማርት ኮንትራክት ስማርት ውዕልካ እናሃነጽካ ኣውቶማቲክ ናይ ፈተነ ስክሪፕት ምጽሓፍ ወሳኒን ኣዝዩ ዝምከርን እዩ። ከም ክልተ ረቛሒታት ዘለዎ ምርግጋጽ (2FA) ኮይኑ ይሰርሕ፣ ቅድሚ ናብቲ ቀጥታዊ መርበብ ምዝርጋሕካ ስማርት ውዕልካ ከምቲ ትጽቢት ዝግበረሉ ስራሕ ከም ዝሰርሕ የረጋግጽ። cjs. ኣብ ውሽጢ እቲ ፋይል ነዚ ኮድ ኣብ ታሕቲ ንለጥፎ : ኣብ ትሕቲ እቲ test ማህደር ሓድሽ ፋይል ፍጠር፣ Coffee. 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"); }); }); }); እዚ ኮድ እዚ ንኣሰራርሓ ናይቲ ናይ ቡን ስማርት ውዕል ይፍትን። ንሱ ድማ ንምውፋር ዝግበር ፈተነታት፡ ቡን ንምግዛእ፡ ከምኡ’ውን ቀጥታዊ ዝውውር ኢተር ናብ ውዕል ምሕላው የጠቓልል። ምብትታን ኣብዚ ኣሎ፤ ተግባር መትሓዚ: 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 }; } : ሓድሽ ናይ ውዕል ምሳሌ ይፈጥርን ናይቲ ኣዋፋሪ ኣካውንት ተጠቒሙ የዋፍሮን። Deploys the Coffee contract : ንምውፋር ዘድሊ ጋዝ ይግምት። ጋዝ ይግምት : እቲ ዝተዋፈረ ውዕል ኣብነት፣ ኣዋፋሪን ዓዳጊን ሕሳባት። ምምላስ ናይ ምውፋር ፈተነታት 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 totalEtherReceived ናይ ቡን መርመራታት ምግዛእ 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 totalEtherReceived ፈተና ፋንክሽን ፋልባክ 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"); }); }); : ኢተር ብቐጥታ ናብቲ ውዕል ምልኣኽ (ንፋንክሽን ከይጸዋዕካ) ነቲ ትራንዛክሽን ከም ዝምለስ የረጋግጽ። ኣብ ቀጥታዊ ምትሕልላፍ ኢተር ምምላስ ምፍታን ስማርት ኮንትራክት እቲ ናይ ፈተና ስክሪፕት ምስጸሓፍካ ድማ : ዝጽውዑ ናይ ምዝገባ መልእኽትታትን ናይ ውዕል ተለዋዋጢ ዋጋታትን ክትሕትም ትኽእል። ከምዚ ጌርካ ከተእቱ ኣለካ፤ ውዕላትካን ፈተነታትካን ኣብ ሃርድሃት ኔትወርክ ከተካይድ ከለኻ ፡ ካብ ኮድ ሶሊዲቲካ console.log() ንኽትጥቀመሉ ድማ ኣብ ናይ ውዕል ኮድካ hardhat/console.sol //SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "hardhat/console.sol"; contract Coffee { //... } ነቲ ውዕል ንምፍታን ኣብ ተርሚናልካ ነዚ ዝስዕብ ትእዛዝ ኣካይድ፤ npx hardhat test ከምዚ ኣብ ታሕቲ ዘሎ ውጽኢት ክህልወካ ይግባእ፤ እዚ ድማ እቲ ስማርት ውዕልካ በቲ ትጽቢት ዝግበረሉ መንገዲ ከም ዝሰርሕ ዘርኢ እዩ። npx hardhat test እንተ ኣካይድካ ብኣውቶማቲክ ነቲ ስማርት ውዕል ኣኪቡ ይፍትኖ። ክትፍትንዎ ትኽእሉ ኢኹም ኣብ ክፍሊ ኮመንት ድማ ክትሕብሩኒ ትኽእሉ ኢኹም። ምውፋር ስማርት ኮንትራክት ኣብዚ፡ ስማርት ውዕልካ ናብ Testnet ንስማርት ውዕልካ ኣብ ንEthereum mainnet ዝመስል ሃዋህው ክትፍትኖ የኽእለካ ርኡይ ወጻኢታት ከየጋጠመካ። ብተግባር ናይቲ dApp ንፉዕ እንተኾንካ፡ ድሕሪኡ ናብ Ethereum Mainnet ዳግማይ ክትዝርግሕ ትኽእል ኢኻ። ሰፖልያ ቴስትነት ከተዋፍር ኢኻ። ነቲ dotenv packageን እዞም ጽግዕተኛታትን ጽዓኑ። npm install dotenv npm install --save-dev @nomicfoundation/hardhat-web3-v4 'web3@4' እዚ ድማ ኣብቲ 'node_modules' ዝብል ፎልደር ብምእታው ኣብ ፕሮጀክትካ Web3.Jsን Dotenvን ክውስኸሉ እዩ። ናብ hardhat.config.cjs ፋይልካ ኣእትዎም require('dotenv').config(); require("@nomicfoundation/hardhat-toolbox"); require("@nomicfoundation/hardhat-web3-v4"); const HardhatUserConfig = require("hardhat/config"); module.exports = { solidity: "0.8.24", } }; ፋይል ። ኣብ ሱር ማህደርና .env ንፍጠር ካብ ሜታማስክ ቦርሳኻን dRPC ኤፒኣይ መፍትሕካን ናይ ኣካውንትካ ብሕታዊ መፍትሕ ውሰድ። ኣብ ፋይልካ .env ኣቐምጦም ። DRPC_API_KEY=your_drpc_api_key PRIVATE_KEY=your_wallet_private_key ነቲ ፤ hardhat.config.cjs ፋይል ን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}`], } } }; ኣብ ትሕቲ ዝብል ኣቃፊራ ፣ ignition/module ሓድሽ ስክሪፕት ፋይል ፍጠር deploy.cjs ድማ ስመዮ ። ስማርት ውዕልካ ንምውፋር እዚ ዝስዕብ ኮድ ወስኸሉ፤ const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules"); const CoffeeModule = buildModule("CoffeeModule", (m) => { const coffee = m.contract("Coffee"); return { coffee }; }); module.exports = CoffeeModule; ኣብ ተርሚናልካ ነዚ ዝስዕብ ትእዛዝ ብምስራሕ ነቲ ስማርት ውዕል ኣዋፍሮ፤ npx hardhat ignition deploy ./ignition/modules/deploy.cjs --network sepolia ድሕሪ ምዝዋር ኮማንድ ፕሮምፕት ፣ ጽሓፍ። ኣብ ዕዉት ምውፋር ኣድራሻ ናይቲ ዝተዋፈረ ስማርት ውዕልካ ኣብቲ ተርሚናል ክትሪኦ ኣለካ። Confirm deploy to network sepolia (11155111)? (y/n) y ኣብቲ ፋይል እውን ነቲ ናይ ውዕል ኣድራሻ ክትረኽቦ ትኽእል ኢኻ። deployed_addresses.json እንቋዕ ሓጎሰካ፡ ስማርት ውዕልካ ናብ ሰፖልያ ቴስትነት ብዓወት ኣዋፊርካዮ ኣለኻ። 🎉 መደምደምታ እዚ ጽሑፍ እዚ ከመይ ጌርካ ናይ ክፍሊት ስማርት ውዕል ትጽሕፍ፣ ትፍትኖ፣ ትእክቦን ትዝርግሖን ስማርት ውዕል ብሃርድሃት CLI ተጠቂምካ ምሂሩካ ኣሎ። ኣብ ዝቕጽል ጽሑፍ፡ ነዚ dApp ዝኸውን ቅድመ-መወዳእታ ምህናጽ ክትመሃሩ ኢኹም። እዚ UI እዚ ዝሓቖፈ ክኸውን እዩ፤ ንብዝሒ ዝተዓደገ ቡን ዝምልከት ናይ ምእታው ዓውዲ። ናይ ክፍሊት ትራንዛክሽን ዝጅምርን ካብ ሕሳብካ ዝቖርጽን መጠወቒ። Display ጠቕላላ ዝተዓደገ ቡንን ዝተረኸበ መጠን ገንዘብን ብኢተርን USDን። ዋጋ ቡን ንባዕሉ ብኤተርን USDን ክልቲኡ። መጣቀሲ ኪኖ ነባሪ መልእኽትታት፡ ምምራሕ ብሕታዊ ጌጋታት ኣብ ጽኑዕነት ኣብ ጽንዓት ብሕታዊ ጌጋታት ምምራሕ፡ ስማርት ውዕላትካ ኪኖ ነባሪ መልእኽትታት ኣልዕል ሶሊዲቲ ፋንክሽን እንታይ እዮም? ኣብ ጽኑዕነት ዝርከቡ ፍጻመታት እንታይ እዮም? ← ዝሓለፈ ጽሑፍ ዝቕጽል ጽሑፍ →