ቴክኖሎጂ ኣብ ኣገልግሎት ወዲ ሰብ ክኸውን ኣለዎ። ድሮ ንብዙሓት ዓውድታት ሰውራ ዘምጽአ ቴክኖሎጂ ብሎክቸይን፡ ንዓውዲ ሕርሻ እውን ክቕይሮ ይኽእል እዩ። ነዚ ዘይተማእከለ ቴክኖሎጂ ናብ ቀንዲ ናይ ምቕባል ኣንፈት ንምምጻእ፡ ናብ ሰፊሕ ተጠቀምቲ ምእንቲ ክንኣቱ፡ ኣብ መወዳእታ ድማ ናይ ኣጠቓቕማ ፍጻመታት ክንውስኽ፡ ናብ ሓፈሻዊ ህዝቢ ንምብጻሕ ከነቃልሎ ይግባእ። ኣብዚ ትምህርቲ፡ ተጠቀምቲ ኣብ መርበብ ብሎክቸይን ሩትስቶክ (RSK) ፍርያት ሕርሻ ክገዝኡን ክሸጡን ዘኽእሎም ዘይተማእከለ ኣፕሊኬሽን (dApp) ክንሃንጽ ኢና። እቲ ቀንዲ ዕላማ ኣብ መርበብ ብሎክቸይን ዝሰርሕ dApp ምህናጽ እዩ። ዝኾነ ዓይነት ተጠቃሚ ብዘይ ካብ መጠን ንላዕሊ ሰብኣዊ ምትእትታው ፍርያቱ ብምሻጥ ብቐሊሉ ክረኽቦ ዝኽእል ፍርያት ክውስኽ ይኽእል። ኣብ መጀመርታ እቲ ኣፕ ኣብ ቴስትኔት ሩትስቶክ ተፈቲኑ፡ ዳርጋ ኣብ ምፍራይ ድሉው ኩነታት እዩ ዘሎ (Just ናብ mainnet ናይ ሩትስቶክ ንምቕያር ንኣሽቱ ምትዕርራያት ኣድለየ)። እቲ ፕሮጀክት ድሮ ኣብ GitHub ተሰቒሉ ስለዘሎ ነቲ መኽዘን ክሎን ጥራይ ጌርካ ባዕልኻ ክትፍትኖ ትኽእል። ነዚ ድማ ኣብ እየ ዝመርጽ። ግን፡ ኣብዚ ትምህርቲ፡ ዝኾነ ዓይነት ተጠቃሚ ነቲ ትምህርቲ ብደረጃ ብቐሊሉ ንምርዳእ፡ dApp ናቱ ክሃንጽ ብዕምቆት ክንመርሕ ንፍትን። ነቲ ናይ ፍሮንቴንድ ኮድ ካብ መኽዘን GitHub ኣውሪድካ፡ ናብቲ ዝምልከቶ ማህደር ክትውስኾ ሓሳብ ክንሕብር ንኽእል ኢና። ካብ ምድላው እቲ ፕሮጀክት ክሳብ ምዝርጋሕ ስማርት ውዕላትን ምፍጣር መስተጋብራዊ ፍሮንቴንድ ምስ ሓቀኛ ግዜ ባህርያትን ኩሉ ክንሽፍኖ ኢና። Readme.md GitHub ቅድሚ ምጅማርና AgriMarket ዝበሃል dApp ክንሃንጽ ዕላማ ኣለና እዚ ድማ እዞም ዝስዕቡ ባህርያት ክህልዎ ትጽቢት ይግበር፤ ተጠቀምቲ ብዝድገፉ ቦርሳታት (ኣብ ጉዳይና ሜታማስክ) ኣቢሎም ንባህርያት Web3 ክረኽቡ የኽእሎም። ተጠቀምቲ ቦርሳኦም ምስ dApp ብምትእስሳር ፍርያቶም ምስ ዋጋታቶም ክውስኹ የኽእሎም። እቲ ኣፕ ምስ ሜታማስክ ብምትሕብባር ነቲ ናይ ስማርትኮንትራክት ጻውዒታት የረጋግጾ። ተጠቀምቲ ኣብቲ ሳጹን ፍርያት ክውስኹ ይኽእሉ እዮም፡ dApp ድማ ዋላ ኣብቲ ሳጹን ብዙሓት ፍርያት እንተሃልዮም ትራንዛክሽን ከበግስ ይኽእል። ተጠቀምቲ ካብ ክልቲኡ ሳጹናት ከምኡ’ውን ካብ ገጽ ዝርዝር ፍርያት ኣብ ሓቀኛ ግዜ መፍለጢታት፡ ቅብሊታት ትራንዛክሽንን ናይ ፍርያት ምእላይ ባህርያትን ክረኽቡ ይኽእሉ። 📥ቅድመ ረቛሒታት - ቅድሚ ምጅማርና፡ ኣብ ማሽንኩም እዞም ዝስዕቡ ከም ዝተተኽሉ ኣረጋግጹ፤ Node.js (v14 ወይ ልዕሊኡ) npm ወይ ፈትሊ ትሩፍል ወይ ሃርድሃት ንልምዓት ስማርት ውዕል ንRSK testnet ዝተዋቕረ መቐጸልታ ሜታማስክ Git ንመቆጻጸሪ ስሪት። ከም VSCode ዝኣመሰለ IDE 📥ኣወዳድባ ፕሮጀክት 👉ናይ ፕሮጀክት ማህደር ምፍጣር በጃኹም ኣብ ምሉእ መስርሕ ምዕባለናን ፈተነናን ናይዚ ቀንዲ ፕሮጀክት ማህደር ከም እትመርጹ ኣረጋግጹ። 👉ናይ ፕሮጀክት ማህደር ምጅማር ኣብ ተርሚናል ነዞም ዝስዕቡ ትእዛዛት ብምስራሕ ንፕሮጀክትካ ሓድሽ ማህደር ፍጠር፤ mkdir rsk-agri-marketplace cd rsk-agri-marketplace 👉ሓድሽ ፕሮጀክት npm ምጅማር፤ npm init -y 👉ፕሮጀክት ትሩፍል ምጅማር ነቲ ስማርት ውዕል ንምጥርናፍን ንምምዕባልን Truffle ንጥቀም ኣለና ስለዚ ብመንገዲ ሱር ማህደር ንጅምሮ፤ truffle init እዚ መሰረታዊ ኣቃውማ ይፈጥር፦ • - • - • - • - contracts/ ውዕላት ሶሊዲቲ ዝሓዘ migrations/ ስክሪፕት ምዝርጋሕ test/ ንውዕላትካ ዝኸውን ፈተነታት truffle-config.js ፋይል ውቅር ትሩፍል 📥ናይ ከባቢ ተለዋዋጢ ምውቃር ስሱዕ ሓበሬታ ከም ናይ ብሕቲ መፍትሕ፣ ፒማታ ኤፒኣይ መፍትሕ ወዘተ ኣብ .env ፋይል ክኽዘን ኣለዎ። 👉dotenv ምትካል npm install dotenv 👉.env ዝብል ፋይል ምፍጣር ኣብቲ ሱር ማህደር ከምዚ ዝስዕብ ኣቃውማ ዘለዎ .env ፋይል ንፍጠር፤ REACT_APP_PINATA_API_KEY=Your API Key REACT_APP_PINATA_SECRET_API_KEY=Secret API Key MNEMONIC=12 words mnemonic key RSK_TESTNET_URL=https://public-node.testnet.rsk.co REACT_APP_CONTRACT_ADDRESS=Contract Address በጃኹም ነቲ ፋይል ብዘይ ተወሳኺ ቦታታት ወይ ዘይምስምማዕ ፊደላት ፍጠሩ እንተዘይኮይኑ ድሒሩ ጸገማት ከጋጥመኩም እዩ። በጃኹም፡ ነዚ እዚ ዘክርዎ ምኽንያቱ ድሒርኩም ነቲ ስማርት ውዕል ትዕብይዎ ስለዘለኹም። ፒናታ ኤፒኣይ ውሰድ ። .env ስጉምቲ ካብዚ 📥ምስ RSK Testnet ምትእስሳር 👉truffle-config.js ምዕራፍ ምግባር ድሮ ዝተፈጥረ truffle-config.js ኣብ ማህደር ፕሮጀክትካ ክትሪኦ ትኽእል ኢኻ። በቃ ነቲ ኮድ ኣፕዴት ብምግባር ምስ RSK testnet ብእኡ ኣቢልና ክንራኸብ ንኽእል። require('dotenv').config(); const HDWalletProvider = require('@truffle/hdwallet-provider'); module.exports = { networks: { development: { host: "127.0.0.1", port: 8545, network_id: "*", }, rskTestnet: { provider: () => new HDWalletProvider({ mnemonic: { phrase: process.env.MNEMONIC, }, providerOrUrl: `https://public-node.testnet.rsk.co`, chainId: 31, // RSK Testnet ID pollingInterval: 15000, }), network_id: 31, gas: 2500000, gasPrice: 60000000, confirmations: 2, timeoutBlocks: 60000, skipDryRun: true, }, }, compilers: { solc: { version: "0.8.20", }, }, db: { enabled: false, }, }; 👉HDWalletProvider ምትካል npm install @truffle/hdwallet-provider 📥ስማርት ኮንትራክት ልምዓት ናይ ዕዳጋ ውዕል ክንፈጥር ኢና። 👉OpenZeppelin Contracts ምትካል ድሕነትን ስሉጥ ኣሰራርሓን ስማርት ውዕልና ንምዕባይ ውዕላት OpenZeppelin ንጥቀም ኣለና፣ ስለዚ ኣብ ተርሚናል ነዚ ዝስዕብ ትእዛዝ ብምስራሕ ንጽዓኖ፤ npm install @openzeppelin/contracts 👉ኣብ ማህደር ምፍጣር፤ contracts/ Marketplace.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; contract Marketplace is ReentrancyGuard, Pausable { uint public productCount = 0; struct Product { uint id; address payable seller; string name; string description; string imageHash; // IPFS hash uint price; // Price in tRBTC bool active; } mapping(uint => Product) public products; event ProductCreated( uint id, address seller, string name, string description, string imageHash, uint price, bool active ); event ProductPurchased( uint id, address seller, address buyer, uint price ); event ProductRemoved(uint id, address seller); function createProduct( string memory _name, string memory _description, string memory _imageHash, uint _price ) public whenNotPaused { require(bytes(_name).length > 0, "Name is required"); require(_price > 0, "Price must be positive"); // Price is expected in tRBTC productCount++; products[productCount] = Product( productCount, payable(msg.sender), _name, _description, _imageHash, _price, true ); emit ProductCreated( productCount, msg.sender, _name, _description, _imageHash, _price, true ); } function purchaseProducts(uint[] memory _ids) public payable nonReentrant whenNotPaused { uint totalCost = 0; for (uint i = 0; i < _ids.length; i++) { Product storage _product = products[_ids[i]]; require(_product.id > 0 && _product.id <= productCount, "Invalid product ID"); require(_product.active, "Product is not active"); require(_product.seller != msg.sender, "Seller cannot buy their own product"); totalCost += _product.price; } require(msg.value >= totalCost, "Insufficient funds"); for (uint i = 0; i < _ids.length; i++) { Product storage _product = products[_ids[i]]; (bool success, ) = _product.seller.call{value: _product.price}(""); require(success, "Transfer failed to the seller"); // Emit purchase event (product can be bought again) emit ProductPurchased( _product.id, _product.seller, msg.sender, _product.price ); } } function removeProduct(uint _id) public { Product storage _product = products[_id]; require(_product.id > 0 && _product.id <= productCount, "Invalid product ID"); require(_product.seller == msg.sender, "Only the seller can remove the product"); _product.active = false; // Mark the product as inactive emit ProductRemoved(_id, msg.sender); } function getProduct(uint _id) public view returns (Product memory) { require(_id > 0 && _id <= productCount, "Invalid product ID"); Product memory product = products[_id]; require(product.active, "Product is not available"); return product; } function pause() public { _pause(); } function unpause() public { _unpause(); } } 👉ኣብ ናይ Migration Script ምጽሓፍ migrations/2_deploy_contracts.js const Marketplace = artifacts.require("Marketplace"); module.exports = function (deployer) { deployer.deploy(Marketplace); }; 👉ውዕላት ምጥርናፍን ምዝርጋሕን። ነቲ ውዕል ብመንገዲ ተርሚናል ንምጥርናፍ ነዚ ዝስዕብ ኮድ ኣካይድ፤ truffle compile ኩሉ ብትኽክል እንተኸይዱ ኣብ ተርሚናል ከምዚ ዓይነት ነገር ክትሪኢ ትኽእል ኢኻ፤ ናብ ናይ Rootstock testnet ንምውፋር ኣብ ተርሚናል ነዚ ዝስዕብ ትእዛዝ ኣካይድ። Marketplace.sol truffle migrate --network rskTestnet ቅድሚ ውዕልካ ምዝርጋሕካ ኣብቲ ቦርሳ ገለ መጠን tRBTC የድልየካ። ካብ ፋውሰት RSK ውሰድዎ ። ኣብዚ ድሕሪ እቲ ዕዉት መስርሕ ኣብዚ ዝስዕብ ተርሚናል መልእኽቲ ክትሪኢ ኢኻ፤ ኣብ ፋይል ክትረክብ ኢኻ ዘክርዎ፣ ነዚ ፋይል ናብ ካልእ ማህደር ክትቅድሖ ኢኻ። \build\contracts\Marketplace.json Marketplace.json ምዕባለ ፍሮንትኤንድ ንዕዳጋ dApp ሕጂ ነቶም ስማርት ውዕላት ኣዋፊርናዮም ኣለና፡ ተጠቀምቲ ምስኡ ክራኸቡ ዘኽእሎም ንዕዳጋ ዝኸውን ሰሓቢ ቅድመ-ገጽ ክንሃንጽ ኢና። እቲ ቅድመ-ገጽ ከም ዝርዝር ፍርያት፡ ፍርያት ምውሳኽ፡ ምዕዳግ፡ ኣብ ሳጹን ፍርያት ምውሳኽ/ምእላይ፡ ትራንዛክሽን ምክትታል፡ ከምኡ’ውን ኣብ ሓቀኛ ግዜ ግብረ-መልሲ ከም መፍለጢታትን ናይ ምዕባለ ባርን ዝኣመሰሉ ባህርያት ክህልዎ እዩ። 📥ግንባር ልምዓት 👉ኣፕሊኬሽን ሪኣክት ምጅማር ንፍሮንትኤንድ ሪኣክት ክንጥቀም ኢና። ኣብቲ ናይ ፕሮጀክት ማህደር ሓድሽ ሪኣክት ኣፕ ምጅማር። npx create-react-app client ናብቲ ናይ ዓሚል ማህደር ንኺድ። cd client ንUI ዝኸውን Web3ን Bootstrapን ንጽዓን። npm install web3 bootstrap 👉ኣቃውማ ፕሮጀክት ከምቲ ኣብ ስእሊ 1 ንርእዮ ዘለና ንቕድሚት ዝኸውን መዋቕር ከድልየካ እዩ። 👉Web3 Setup ኣብ src/utils/Marketplace.json ምስቲ ስማርት ውዕል ንምትእስሳር፡ ነቲ ABI (Application Binary Interface) ከነእቱ ኢና። ካብ Truffle directory ናትካ ABI ከምቲ ኣብ ዝተጠቕሰ ናብ folder ቅዳሕ። build/contracts Marketplace.json Step client/src/utils/ Web3 setup ኣብ ፋይል ኣሎ። ካብ ኣውሪድና ከምቲ ኣብ ስእሊ 1 ንርእዮ ዘለና ኣብቲ ዝምልከቶ ማህደር ኣቐምጦ። App.js GitHub 👉 ኣብ ሓቀኛ ግዜ መፍለጢታትን ፕሮግረስ ባርን ንሓቀኛ ግዜ መፍለጢታት፡ ከም ቤተ-መጻሕፍቲ ዝመስል ክንወሃሃድ ኢና። ንገስጋስ ባር እውን ክትጥቀም ትኽእል ኢኻ። react-toastify react-bootstrap ኣብቲ ማህደር ሪኣክት ቶስቲፋይ ንጽዓኖ client npm install react-toastify 👉ንኤችቲቲፒ ሕቶታት ዝኸውን ኣክሲዮስ ምትካል (ናብ ኤፒኣይ ፒናታ)፤ npm install axios ጽቡቕ ኣሎ፡ ሕጂ በጃኻ ኩሎም ናይ Frontend ክፍልታት ካብቲ ዓሚል ማህደር (ንኣቃፊት+ፋይላት ሓዊስካ) ናይ ኣውርድ ። ኣብቲ ዝምልከቶ ማህደር ድማ ኣቐምጦም። GitHub መኽዘን 📥ናይ መወዳእታ ምትንኻፍን ምስ ኣፕካ ምትእስሳርን 👉ሕጂ፡ ምስ dApp ክትራኸቡ ትኽእሉ ኢኹም። ኣብ ተርሚናል ነዚ ዝስዕብ ትእዛዝ ብምጥቃም react app ክትሰርሕ ትኽእል ኢኻ፤ npm start ነቲ ነባሪ መርበብ ሓበሬታ ብኣውቶማቲክ ክኸፍቶ እዩ። በጃኹም እቲ ናይ MetMask መርበብ ሓበሬታ መቐጸልታ ተተኺሉን ነቲ RSK testnet ብግቡእ ከም ዝተዋቕረካን ኣረጋግጽ ( ቅኑዕ መርበብ ንምምራጽ መምርሒ ናይቲ ፕሮጀክት ክትክተል ትኽእል ኢኻ)። ኣብዚ ሕጂ፡ react app ነቲ MetaMask wallet extension ይጽውዕ፡ በጃኹም ነቲ ጻውዒት ኣረጋግጹ። ብድሕሪኡ ከምቲ ኣብዚ ዝስዕብ ስእሊ ንርእዮ ዘለና ነቲ ዝተኣሳሰረ ቦርሳ ኣብቲ ቀንዲ መተሓላለፊ ከርእዮ እዩ። እቲ ቅድመ-ገጽ ብዙሕ ባህርያት የቕርበልካ። ፍርያት ክትውስኽ/ክትእለ ትኽእል ኢኻ። ኣብ ነፍሲ ወከፍ እዋን፡ ኣብ መቐጸልታ ቦርሳ ሜታማስክ ነቲ ጻውዒት ከተረጋግጽ ክትሕተት ኢኻ። ነዚ ዝስዕብ gif ርኣዩ፤ ጽቡቕ ሕጂ dApp ነቲ ኣብቲ ሳጹን ዝተወሰኸ ትራንዛክሽን ብግቡእ የሰላስሎ ድዩ ኣይሰርሖን ክትፍትን ትኽእል ኢኻ። ኣብ ትሕቲ “ታሪኽ ትራንዛክሽን” ዝብል ክፍሊ ዝርዝር ታሪኽ ትራንዛክሽን ምስ ኩሉ ቴክኒካዊ ዝርዝር ክትዕዘቡ ትኽእሉ ኢኹም። እቲ ዕድጊ ምስተዛዘመ እቲ ፈንድ ናብቲ ነቲ ፍርያት ናብ dApp ዝወሰኸ ዋና ይለኣኽ። ነቲ App ብሓባር ንፈትኖ: እንኳዕ ደስ በለካ! ኣብ RSK testnet ንdApp ብዓወት ኣማዕቢልናን ፈቲንናዮን ኣለና። ዝደለኻዮ ባህርያት ብምውሳኽ ናብ RSK mainnet ክትቅይሮ ትኽእል ኢኻ። testnet ኣብ ዝተጠቕሰ ቦታ ኮዳት ጥራይ ኣስተኻኽል ከምኡ ውን ነቲ ንፍርያት ድሉው ዝኾነ ኣፕ ንምህናጽ ትጓየ እንተኾንካ ኣብዚ መርምር። ናይቲ ፕሮጀክት ሰነዳት 📥ክህልዉ ዝኽእሉ ብድሆታትን መጻእን፤ ንዕዳጋ ሕርሻ ንምጅማር ሓድሽ ኣገባብ ክኸውን እዩ እዚ ድማ ሓያሎ መስርሓት ከም ኣወሃህባ ፍርያት፣ ምልዓል ወዘተ ዘጠቓልል እዩ።ዓደግትን ሸየጥትን ብዝርዝር ከይፈለጥኩም ናይ ምትእምማን ሕቶታት ክፈጥር ይኽእል እዩ። ካልእ ብድሆ ድማ ገና ኣብ ምዕራፍ ፈተነ ምህላዉ እዩ፡ እቶም ተጠቀምቲ ድማ ነዚ ዝምዕብል ዘሎ ቴክኖሎጂ ከመይ ከም ዝመላለሱ ኣይንፈልጥን። ስለዚ፡ ሓረስቶትን ተጠቀምትን ሓደስቲ ቴክኖሎጂታት ንኽቕበሉ ትምህርትን ስልጠናን ኣገዳሲ እዩ። ከምኡ እውን እኹል ምትሕብባር ንፍርያት ሕርሻ ዘላቒ ዘይተማእከለ ዕዳጋ ንምምዕባል ቁልፊ ረቛሒታት እዮም። መደምደምታ፥ ኣብ ሩትስቶክ (RSK) testnet ዘይተማእከለ ዕዳጋ ሕርሻ ብዓወት ሃኒጽና። ጸጥታ ከም ቀዳምነት ተዋሂቡ ስለዚ እዩ ድማ ንኮድ ስማርትኮንትራክት ንምሕላው ሓያሎ ስጉምትታት ዝውሰድ ውዕላት ኦፐንዘፐሊን ብምጥቃም። ዝተፈተነ dApp ዳርጋ ኩሎም እቶም ሓደ ቀሊል ዘይተማእከለ ዕዳጋ ክህልዎም ዝግባእ ኣድለይቲ ባህርያት ዝሓዘ ኮይኑ፡ ኣብ Rootstock’s mainnet app ክትጅምር እንተሓሲብካ ግን ብዝያዳ ባህርያት ከተዕብዮ ትኽእል ኢኻ። ከምኡ’ውን ኩሉ ከምቲ ዝተሓሰበን ብዘይ ገለ ጸገምን ከም ዝሰርሕ ንምርግጋጽ ድሕነት ኣብ ግምት ኣእትዉ። ንሕና ንኹሉ ትራንዛክሽን ንምቕጻል ናይ ሩትስቶክ ቅልጡፍ ናይ ትራንዛክሽን መስርሕ ባህርያት ምስ ትሑት ናይ ትራንዛክሽን ክፍሊት ክንጥቀመሉ ፈቲንና ኣለና እዚ ድማ ነቲ ዕሉል ናይ ቢትኮይን ናይ ጽቕጥቕጥ ጉዳይ ክፈትሕ እዩ። ብርግጽ እዞም ዓይነት ዘይተማእከለ ዕዳጋታት ክንድዚ ዝኣክል ጉዳያት ክገጥሙ ኣለዎም፡ እንተኾነ ግን ብተፈጥሮና ናጽነት ኣብ እንደልየሉ ዘለና እዋን፡ ኣብ መጻኢ ዝያዳ ዘይተማእከለ ዕዳጋ ክንረክብ ተስፋ ክንገብር ንኽእል።