Tehnologia trebuie să fie în slujba omenirii. Tehnologia blockchain, care a revoluționat deja multe sectoare, poate transforma și domeniul agriculturii. Pentru a aduce această tehnologie descentralizată la tendința de adoptare generală, ar trebui să o simplificăm pentru a ajunge la publicul larg, astfel încât să putem ajunge la utilizatorii mai largi, crescând în cele din urmă cazurile de utilizare.
În acest tutorial, vom construi o aplicație descentralizată (dApp) care permite utilizatorilor să cumpere și să vândă produse agricole în rețeaua blockchain Rootstock (RSK). Scopul principal este de a construi un dApp care rulează pe rețeaua blockchain. Orice fel de utilizatori pot adăuga cu ușurință produse pentru a le câștiga prin vânzarea produselor agricole fără intervenție umană excesivă.
Inițial, aplicația a fost testată pe rețeaua de testare Rootstock și este aproape în starea de producție (a fost nevoie doar de ajustări minore pentru a trece la rețeaua principală a Rootstock). Proiectul este deja încărcat în GitHub, așa că puteți doar să clonați depozitul pentru a-l testa singur.
Pentru aceasta, prefer Readme.md
pe GitHub . Dar, în acest tutorial, încercăm să ghidăm în profunzime, astfel încât orice tip de utilizator să își poată construi dApp cu ușurința de a înțelege tutorialul pas. Vă putem propune să descărcați codul Frontend din depozitul GitHub și să îl adăugați în directorul corespunzător. Vom acoperi totul, de la configurarea proiectului până la implementarea contractelor inteligente și crearea unui Frontend interactiv cu funcții în timp real.
Înainte de a începe, ne propunem să construim o aplicație dApp numită AgriMarket, care este de așteptat să aibă următoarele caracteristici:
👉Creați directorul de proiecte
Vă rugăm să vă asigurați că preferați directorul acestui proiect principal pe parcursul întregului nostru proces de dezvoltare și testare.
👉Inițializați directorul de proiecte
Creați un director nou pentru proiectul dvs. rulând următoarele comenzi în terminal:
mkdir rsk-agri-marketplace cd rsk-agri-marketplace
👉Inițializați un nou proiect npm:
npm init -y
👉Inițializați Proiectul Trufei
Folosim Truffle pentru a compila și dezvolta contractul inteligent, așa că inițializați-l prin directorul rădăcină:
truffle init
Aceasta creează structura de bază: • contracts/
- Conține contracte Solidity • migrations/
- Scripturi de implementare • test/
- Teste pentru contractele dvs. • truffle-config.js
- Fișier de configurare Truffle
Informațiile sensibile, cum ar fi cheile private, cheia API Pimata etc., ar trebui să fie stocate într-un fișier .env.
👉 Instalați dotenv
npm install dotenv
👉Creați un fișier .env
În directorul rădăcină, creați un fișier .env cu următoarea structură:
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
Creați fișierul .env
fără spații suplimentare sau nepotriviri de caractere, altfel veți întâmpina dificultăți mai târziu. Vă rugăm să rețineți acest pas , deoarece actualizați contractul inteligent mai târziu. Obțineți Pinata API de aici .
👉Actualizați truffle-config.js
Puteți vedea truffle-config.js deja creat în directorul proiectului dumneavoastră. Doar actualizați codul, astfel încât să putem interacționa cu testnetul RSK prin intermediul acestuia.
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, }, };
👉 Instalați HDWalletProvider
npm install @truffle/hdwallet-provider
Vom crea un contract de piață.
👉Instalați OpenZeppelin Contracts
Folosim contracte OpenZeppelin pentru a spori securitatea și buna funcționare a contractului nostru inteligent, așa că instalați-l rulând următoarea comandă în terminal:
npm install @openzeppelin/contracts
👉Creează Marketplace.sol
în contracts/
director:
// 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(); } }
👉Scrieți scriptul de migrare în migrations/2_deploy_contracts.js
const Marketplace = artifacts.require("Marketplace"); module.exports = function (deployer) { deployer.deploy(Marketplace); };
👉Compilați și implementați contracte
Rulați următorul cod pentru a compila contractul prin terminal:
truffle compile
Dacă totul merge corect, puteți vedea ceva de genul acesta în terminal:
Rulați următoarea comandă în terminal pentru a implementa Marketplace.sol
în rețeaua de testare a Rootstock.
truffle migrate --network rskTestnet
Aveți nevoie de câteva cantități de tRBTC în portofel înainte de a vă implementa contractul. Obțineți-l de la robinetul RSK aici .
După procesul de succes, veți vedea mesajul în următorul terminal:
Veți găsi fișierul Marketplace.json
în \build\contracts\Marketplace.json
amintiți-l, veți copia acest fișier într-un alt director.
Dezvoltare front-end pentru Marketplace dApp
Acum că am implementat contractele inteligente, vom construi un frontend atractiv pentru piață, care să permită utilizatorilor să interacționeze cu acesta. Interfața va avea caracteristici precum listări de produse, adăugare de produse, cumpărare, adăugare/eliminare de produse din coș, urmărirea tranzacțiilor și furnizarea de feedback în timp real, cum ar fi notificări și o bară de progres.
👉Inițializați aplicația React
Vom folosi React pentru frontend.
Inițializați o nouă aplicație React în directorul proiectului.
npx create-react-app client
Navigați la directorul client.
cd client
Instalați Web3 și Bootstrap pentru UI
npm install web3 bootstrap
👉Structura proiectului
Veți avea nevoie de structura pentru frontend așa cum se arată în Figura 1.
👉Configurare Web3 în src/utils/Marketplace.json
Pentru a interacționa cu contractul inteligent, vom importa ABI (Application Binary Interface).
Marketplace.json
ABI din directorul Truffle build/contracts
în folderul client/src/utils/
așa cum este menționat în Pasul .
App.js
Descărcați-l de pe GitHub și plasați-l în directorul corespunzător, așa cum se arată în Figura 1.
👉 Notificări în timp real și bare de progres
Pentru notificări în timp real, vom integra un react-toastify
asemănător bibliotecii. De asemenea, puteți utiliza react-bootstrap
pentru barele de progres.
Instalați React Toastify în directorul client
npm install react-toastify
👉 Instalați Axios pentru solicitări HTTP (la API-ul Pinata):
npm install axios
Bine, acum vă rugăm să descărcați toate componentele Frontend din folderul client (inclusiv folderul + fișierele) din depozitul GitHub . Și plasați-le în directorul corespunzător.
👉Acum, puteți interacționa cu dApp. Puteți rula aplicația React folosind următoarea comandă în terminal:
npm start
Se va deschide automat browserul implicit. Vă rugăm să vă asigurați că aveți extensia de browser MetMask instalată și configurată corect rețeaua de testare RSK (puteți urma ghidul proiectului pentru a selecta rețeaua corectă aici ).
Acum, aplicația react invocă extensia portofel MetaMask, vă rugăm să confirmați apelul. Apoi va afișa portofelul conectat în interfața principală, așa cum se arată în figura următoare.
Interfața vă oferă o mulțime de funcții. Puteți adăuga/elimina produse. De fiecare dată, vi se va cere să confirmați apelul în extensia portofel MetaMask. Verificați următorul gif:
Ei bine, acum puteți testa dacă dApp procesează corect tranzacțiile adăugate în coș sau nu. Puteți vedea un istoric detaliat al tranzacțiilor în secțiunea „Istoricul tranzacțiilor” cu toate detaliile tehnice. Odată ce achiziția este finalizată, fondul este trimis proprietarului care a adăugat produsele în dApp.
Să testăm împreună aplicația:
Felicitari! Am dezvoltat și testat cu succes dApp-ul în testnetul RSK. Îl puteți comuta pe rețeaua principală RSK adăugând caracteristicile dorite. Doar ajustați codurile oriunde este menționat testnet și verificați, de asemenea, documentația proiectului aici dacă vă grăbiți să construiți aplicația pregătită pentru producție.
Va fi noua abordare de a iniția piața agricolă, care include mai multe procese, cum ar fi livrarea produselor, ridicarea, etc. Fără a cunoaște cumpărătorii și vânzătorii în detaliu, ar putea crea probleme de încredere. O altă provocare este că este încă în fază experimentală și nu știm cum se comportă consumatorii față de această tehnologie în evoluție.
Așadar, educația și formarea sunt esențiale atât pentru fermieri, cât și pentru consumatori, pentru a adopta noi tehnologii. De asemenea, colaborările suficiente sunt factorii cheie pentru dezvoltarea unei piețe descentralizate durabile pentru produsele agricole.
Am construit cu succes o piață agricolă descentralizată pe rețeaua de testare Rootstock (RSK). Securitatea a fost luată drept prioritate, motiv pentru care sunt luate mai multe măsuri pentru a proteja codul smartcontract prin utilizarea contractelor OpenZeppelin. Tested dApp constă din aproape toate caracteristicile necesare pe care ar trebui să le aibă o piață descentralizată simplă, dar o puteți îmbunătăți cu mai multe caracteristici dacă intenționați să lansați aplicația în rețeaua principală a Rootstock. De asemenea, țineți cont de securitate pentru a vă asigura că totul funcționează conform intenției și fără probleme.
Am încercat să folosim funcțiile de procesare rapidă a tranzacțiilor de la Rootstock cu taxe de tranzacție reduse pentru a continua cu toate tranzacțiile care vor rezolva problema notorie a congestiei Bitcoin. Desigur, aceste tipuri de piețe descentralizate trebuie să se confrunte cu atât de multe probleme, dar întrucât căutăm în mod natural libertatea, putem spera că vom găsi o piață mai descentralizată în viitor.