Технология должна служить человечеству. Технология блокчейн, которая уже произвела революцию во многих секторах, может также преобразовать сферу сельского хозяйства. Чтобы сделать эту децентрализованную технологию общепринятой тенденцией, мы должны упростить ее, чтобы она стала доступной широкой публике, чтобы мы могли охватить более широких пользователей, в конечном итоге увеличивая варианты использования.
В этом руководстве мы создадим децентрализованное приложение (dApp), которое позволит пользователям покупать и продавать сельскохозяйственную продукцию в сети блокчейнов Rootstock (RSK). Основная цель — создать dApp, работающее в сети блокчейнов. Любой пользователь может легко добавлять продукты, чтобы зарабатывать, продавая свою сельскохозяйственную продукцию, без чрезмерного человеческого вмешательства.
Первоначально приложение тестировалось в тестовой сети Rootstock, и оно почти готово к производству (нужны лишь незначительные корректировки для переключения на основную сеть Rootstock). Проект уже загружен на GitHub, поэтому вы можете просто клонировать репозиторий, чтобы протестировать его самостоятельно.
Для этого я предпочитаю Readme.md
на GitHub . Но в этом руководстве мы пытаемся дать подробное руководство, чтобы любой пользователь мог создать свое dApp с легкостью понимания руководства пошагово. Мы можем предложить вам загрузить код Frontend из репозитория GitHub и добавить его в соответствующий каталог. Мы рассмотрим все, от настройки проекта до развертывания смарт-контрактов и создания интерактивного Frontend с функциями реального времени.
Прежде чем начать, мы намерены создать dApp под названием AgriMarket, которое, как ожидается, будет иметь следующие функции:
👉Создайте каталог проекта
Пожалуйста, убедитесь, что вы отдаете предпочтение этому основному каталогу проекта на протяжении всего процесса разработки и тестирования.
👉Инициализируйте каталог проекта
Создайте новый каталог для вашего проекта, выполнив следующие команды в терминале:
mkdir rsk-agri-marketplace cd rsk-agri-marketplace
👉Инициализируйте новый проект npm:
npm init -y
👉Инициировать проект Truffle
Мы используем Truffle для компиляции и разработки смарт-контракта, поэтому инициализируем его через корневой каталог:
truffle init
Это создает базовую структуру: • contracts/
- Содержит контракты Solidity • migrations/
- Скрипты развертывания • test/
- Тесты для ваших контрактов • truffle-config.js
- Файл конфигурации Truffle
Конфиденциальная информация, такая как закрытые ключи, ключ API Pimata и т. д., должна храниться в файле .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
без лишних пробелов или несовпадений символов, иначе позже у вас возникнут трудности. Пожалуйста, запомните этот шаг , так как позже вы обновите смарт-контракт. Получите API Pinata здесь .
👉Обновите 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
Мы используем контракты OpenZeppelin для повышения безопасности и бесперебойной работы нашего смарт-контракта, поэтому установите его, выполнив следующую команду в терминале:
npm install @openzeppelin/contracts
👉Создайте Marketplace.sol
в каталоге 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(); } }
👉Напишите скрипт миграции в migrations/2_deploy_contracts.js
const Marketplace = artifacts.require("Marketplace"); module.exports = function (deployer) { deployer.deploy(Marketplace); };
👉Составление и развертывание контрактов
Запустите следующий код для компиляции контракта через терминал:
truffle compile
Если все прошло правильно, в терминале вы увидите что-то вроде этого:
Выполните следующую команду в терминале, чтобы развернуть Marketplace.sol
в тестовой сети Rootstock.
truffle migrate --network rskTestnet
Вам нужно некоторое количество tRBTC в кошельке перед развертыванием вашего контракта. Получите его из крана RSK здесь .
После успешного процесса вы увидите следующее сообщение в терминале:
Файл Marketplace.json
вы найдете в \build\contracts\Marketplace.json
Запомните его, вам нужно будет скопировать этот файл в другой каталог.
Разработка интерфейса для Marketplace dApp
Теперь, когда мы развернули смарт-контракты, мы собираемся создать привлекательный фронтенд для рынка, который позволит пользователям взаимодействовать с ним. Фронтенд будет иметь такие функции, как списки продуктов, добавление продуктов, покупка, добавление/удаление продуктов в корзине, отслеживание транзакций и предоставление обратной связи в реальном времени, такой как уведомления и индикатор выполнения.
👉Инициализация приложения React
Для фронтенда мы будем использовать React.
Инициализируйте новое приложение React в каталоге проекта.
npx create-react-app client
Перейдите в каталог клиентов.
cd client
Установить Web3 и Bootstrap для пользовательского интерфейса
npm install web3 bootstrap
👉Структура проекта
Вам понадобится структура интерфейса, показанная на рисунке 1.
👉Настройка Web3 в src/utils/Marketplace.json
Для взаимодействия со смарт-контрактом мы импортируем ABI (Application Binary Interface).
Marketplace.json
ABI из каталога Truffle build/contracts
в папку client/src/utils/
, как указано в шаге .
App.js
Загрузите его с GitHub и поместите в соответствующий каталог, как показано на рисунке 1.
👉 Уведомления в реальном времени и индикаторы выполнения
Для уведомлений в реальном времени мы интегрируем библиотеку react-toastify
. Вы также можете использовать react-bootstrap
для индикаторов выполнения.
Установите React Toastify в client
каталог
npm install react-toastify
👉Установите Axios для HTTP-запросов (к API Pinata):
npm install axios
Хорошо, теперь, пожалуйста, загрузите все компоненты Frontend из клиентской папки (включая папку+файлы) репозитория GitHub . И поместите их в соответствующий каталог.
👉Теперь вы можете взаимодействовать с вашим dApp. Вы можете запустить свое приложение React, используя следующую команду в терминале:
npm start
Он автоматически откроет браузер по умолчанию. Убедитесь, что у вас установлено расширение браузера MetMask и правильно настроена тестовая сеть RSK (Вы можете следовать руководству проекта, чтобы выбрать правильную сеть здесь ).
Теперь приложение react вызывает расширение кошелька MetaMask, подтвердите вызов. Затем оно отобразит подключенный кошелек в главном интерфейсе, как показано на следующем рисунке.
Интерфейс предлагает вам множество функций. Вы можете добавлять/удалять продукты. Каждый раз вам будет предложено подтвердить вызов в расширении кошелька MetaMask. Проверьте следующий gif:
Ну, теперь вы можете проверить, правильно ли dApp обрабатывает транзакции, добавленные в корзину, или нет. Вы можете увидеть подробную историю транзакций в разделе «История транзакций» со всеми техническими подробностями. После завершения покупки средства отправляются владельцу, который добавил продукты в dApp.
Давайте протестируем приложение вместе:
Поздравляем! Мы успешно разработали и протестировали dApp в тестовой сети RSK. Вы можете переключить его на основную сеть RSK, добавив нужные вам функции. Просто отредактируйте коды везде, где упоминается тестовая сеть, а также проверьте документацию проекта здесь, если вы спешите создать готовое к производству приложение.
Это будет новый подход к инициированию сельскохозяйственного рынка, который включает несколько процессов, таких как доставка продукции, самовывоз и т. д. Без детального знания покупателей и продавцов это может создать проблемы с доверием. Другая проблема заключается в том, что это все еще находится в экспериментальной фазе, и мы не знаем, как потребители относятся к этой развивающейся технологии.
Таким образом, образование и обучение необходимы как для фермеров, так и для потребителей, чтобы принять новые технологии. Кроме того, достаточное сотрудничество является ключевым фактором для развития устойчивого децентрализованного рынка для сельскохозяйственной продукции.
Мы успешно построили децентрализованный сельскохозяйственный рынок на тестовой сети Rootstock (RSK). Безопасность была взята в качестве приоритета, поэтому были приняты некоторые меры для защиты кода смарт-контракта с использованием контрактов OpenZeppelin. Протестированное dApp состоит почти из всех необходимых функций, которые должны быть у простого децентрализованного рынка, но вы можете улучшить его дополнительными функциями, если планируете запустить приложение в основной сети Rootstock. Кроме того, помните о безопасности, чтобы убедиться, что все работает так, как задумано, и гладко.
Мы попытались использовать быстрые функции обработки транзакций Rootstock с низкими комиссиями за транзакции, чтобы продолжить все транзакции, что решит печально известную проблему перегрузки Bitcoin. Конечно, подобные децентрализованные рынки сталкиваются со множеством проблем, но поскольку мы естественным образом стремимся к свободе, мы можем надеяться, что в будущем найдем более децентрализованный рынок.