La tecnología debe estar al servicio de la humanidad. La tecnología blockchain, que ya ha revolucionado muchos sectores, también puede transformar el campo agrícola. Para que esta tecnología descentralizada se convierta en una tendencia de adopción generalizada, debemos simplificarla para que llegue al público en general y así poder llegar a un mayor número de usuarios, aumentando en última instancia los casos de uso.
En este tutorial, crearemos una aplicación descentralizada (dApp) que permita a los usuarios comprar y vender productos agrícolas en la red blockchain de Rootstock (RSK). El objetivo principal es crear una dApp que se ejecute en la red blockchain. Cualquier tipo de usuario puede agregar productos fácilmente para ganar dinero vendiendo sus productos agrícolas sin una intervención humana excesiva.
Inicialmente, la aplicación se probó en la red de prueba de Rootstock y está casi lista para producción (solo se necesitaron pequeños ajustes para cambiar a la red principal de Rootstock). El proyecto ya está cargado en GitHub, por lo que puedes clonar el repositorio para probarlo tú mismo.
Para esto, prefiero Readme.md
en GitHub . Pero, en este tutorial, intentamos guiar en profundidad para que cualquier tipo de usuario pueda crear su dApp con la facilidad de comprender el tutorial paso a paso. Podemos proponerle que descargue el código de Frontend del repositorio de GitHub y lo agregue al directorio apropiado. Cubriremos todo, desde la configuración del proyecto hasta la implementación de contratos inteligentes y la creación de un Frontend interactivo con funciones en tiempo real.
Antes de comenzar, nuestro objetivo es crear una dApp llamada AgriMarket que se espera que tenga las siguientes características:
👉Crear el directorio del proyecto
Asegúrese de preferir este directorio del proyecto principal durante todo nuestro proceso de desarrollo y pruebas.
👉Inicializa el directorio del proyecto
Cree un nuevo directorio para su proyecto ejecutando los siguientes comandos en la terminal:
mkdir rsk-agri-marketplace cd rsk-agri-marketplace
👉Inicializa un nuevo proyecto npm:
npm init -y
👉Iniciar el proyecto Truffle
Estamos usando Truffle para compilar y desarrollar el contrato inteligente, así que inicialícelo a través del directorio raíz:
truffle init
Esto crea la estructura básica: • contracts/
- Contiene contratos de Solidity • migrations/
- Scripts de implementación • test/
- Pruebas para sus contratos • truffle-config.js
- Archivo de configuración de Truffle
La información confidencial, como claves privadas, clave API de Pimata, etc., debe almacenarse en un archivo .env.
👉Instalar dotenv
npm install dotenv
👉Crear un archivo .env
En el directorio raíz, cree un archivo .env con la siguiente estructura:
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
Cree el archivo .env
sin espacios adicionales ni caracteres que no coincidan, de lo contrario tendrá dificultades más adelante. Recuerde este paso porque estará actualizando el contrato inteligente más adelante. Obtenga la API de Pinata desde aquí .
👉Actualizar truffle-config.js
Puedes ver el archivo truffle-config.js ya creado en el directorio de tu proyecto. Solo tienes que actualizar el código para que podamos interactuar con la red de pruebas RSK a través de él.
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, }, };
👉Instalar HDWalletProvider
npm install @truffle/hdwallet-provider
Crearemos un contrato de mercado.
👉Instalar contratos OpenZeppelin
Estamos utilizando contratos OpenZeppelin para mejorar la seguridad y el buen funcionamiento de nuestro contrato inteligente, así que instálelo ejecutando el siguiente comando en la terminal:
npm install @openzeppelin/contracts
👉Crea Marketplace.sol
en el directorio contracts/
:
// 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(); } }
👉Escribe el script de migración en migrations/2_deploy_contracts.js
const Marketplace = artifacts.require("Marketplace"); module.exports = function (deployer) { deployer.deploy(Marketplace); };
👉Compilar e implementar contratos
Ejecute el siguiente código para compilar el contrato a través de la terminal:
truffle compile
Si todo va correctamente, podrás ver algo como esto en la terminal:
Ejecute el siguiente comando en la terminal para implementar Marketplace.sol
en la red de prueba de Rootstock.
truffle migrate --network rskTestnet
Necesitas tener cierta cantidad de tRBTC en la billetera antes de implementar tu contrato. Obténla desde la faucet de RSK aquí .
Luego del proceso exitoso verás el mensaje en la siguiente terminal:
Encontrarás el archivo Marketplace.json
en \build\contracts\Marketplace.json
recuérdalo, copiarás este archivo a otro directorio.
Desarrollo de frontend para la aplicación de mercado
Ahora que hemos implementado los contratos inteligentes, vamos a crear una interfaz atractiva para el mercado que permita a los usuarios interactuar con él. La interfaz tendrá funciones como listados de productos, adición de productos, compras, adición o eliminación de productos del carrito, seguimiento de transacciones y provisión de comentarios en tiempo real, como notificaciones y una barra de progreso.
👉Inicializa la aplicación React
Usaremos React para el frontend.
Inicializar una nueva aplicación React en el directorio del proyecto.
npx create-react-app client
Navegue hasta el directorio del cliente.
cd client
Instalar Web3 y Bootstrap para la interfaz de usuario
npm install web3 bootstrap
👉Estructura del proyecto
Necesitará la estructura para el frontend como se muestra en la Figura 1.
👉Configuración de Web3 en src/utils/Marketplace.json
Para interactuar con el contrato inteligente, importaremos la ABI (Interfaz binaria de aplicación).
Marketplace.json
desde su directorio Truffle build/contracts
a la carpeta client/src/utils/
como se menciona en el Paso .
App.js
Descárguelo de GitHub y colóquelo en el directorio correspondiente, como se muestra en la Figura 1.
👉 Notificaciones en tiempo real y barras de progreso
Para las notificaciones en tiempo real, integraremos una biblioteca similar react-toastify
. También puedes usar react-bootstrap
para las barras de progreso.
Instalar React Toastify en el directorio client
npm install react-toastify
👉Instalar Axios para solicitudes HTTP (a la API de Pinata):
npm install axios
Bien, ahora descargue todos los componentes de Frontend de la carpeta del cliente (incluida la carpeta y los archivos) del repositorio de GitHub y colóquelos en el directorio correspondiente.
👉Ahora puedes interactuar con tu dApp. Puedes ejecutar tu aplicación React usando el siguiente comando en la terminal:
npm start
Se abrirá automáticamente el navegador predeterminado. Asegúrese de tener instalada la extensión del navegador MetMask y de haber configurado correctamente la red de prueba RSK (puede seguir la guía del proyecto para seleccionar la red correcta aquí ).
Ahora, la aplicación React invoca la extensión de billetera MetaMask. Confirme la llamada. Luego, mostrará la billetera conectada en la interfaz principal, como se muestra en la siguiente figura.
La interfaz ofrece muchas funciones. Puede agregar o eliminar productos. Cada vez, se le solicitará que confirme la llamada en la extensión de billetera MetaMask. Vea el siguiente gif:
Ahora puedes comprobar si la dApp procesa correctamente las transacciones añadidas al carrito o no. Puedes ver un historial de transacciones detallado en la sección “Historial de transacciones” con todos los detalles técnicos. Una vez completada la compra, el fondo se envía al propietario que ha añadido los productos a la dApp.
Probemos la aplicación juntos:
¡Felicitaciones! Hemos desarrollado y probado con éxito la dApp en la red de prueba RSK. Puedes cambiarla a la red principal RSK agregando las funciones que desees. Solo ajusta los códigos donde se mencione la red de prueba y también consulta la documentación del proyecto aquí si tienes prisa por crear la aplicación lista para producción.
Será el nuevo enfoque para iniciar el mercado agrícola, que incluye varios procesos como la entrega del producto, la recogida, etc. Sin conocer en detalle a los compradores y vendedores, podría generar problemas de confianza. Otro desafío es que todavía se encuentra en la fase experimental y no sabemos cómo se comportan los consumidores ante esta tecnología en evolución.
Por lo tanto, la educación y la capacitación son esenciales para que tanto los agricultores como los consumidores adopten nuevas tecnologías. Asimismo, la colaboración suficiente es un factor clave para desarrollar un mercado descentralizado y sostenible para los productos agrícolas.
Hemos creado con éxito un mercado agrícola descentralizado en la red de prueba Rootstock (RSK). La seguridad se ha considerado una prioridad, por lo que se han tomado varias medidas para proteger el código de los contratos inteligentes mediante el uso de contratos OpenZeppelin. La dApp probada consta de casi todas las características necesarias que debería tener un mercado descentralizado simple, pero puede mejorarla con más funciones si planea lanzar la aplicación en la red principal de Rootstock. Además, tenga en cuenta la seguridad para asegurarse de que todo funcione como se espera y sin problemas.
Hemos intentado utilizar las funciones de procesamiento rápido de transacciones de Rootstock con tarifas de transacción bajas para continuar con todas las transacciones, lo que resolverá el notorio problema de congestión de Bitcoin. Por supuesto, este tipo de mercados descentralizados tienen que enfrentar muchos problemas, pero como buscamos naturalmente la libertad, podemos esperar encontrar un mercado más descentralizado en el futuro.