기술은 인류에게 봉사해야 합니다. 이미 많은 분야에 혁명을 일으킨 블록체인 기술은 농업 분야도 변화시킬 수 있습니다. 이 분산형 기술을 주류 채택 추세로 이끌기 위해서는 일반 대중에게 도달할 수 있도록 단순화하여 더 광범위한 사용자에게 도달하고 궁극적으로 사용 사례를 늘려야 합니다. 이 튜토리얼에서는 Rootstock(RSK) 블록체인 네트워크에서 사용자가 농산물을 사고 팔 수 있는 분산형 애플리케이션(dApp)을 빌드합니다. 주요 목표는 블록체인 네트워크에서 실행되는 dApp을 빌드하는 것입니다. 모든 유형의 사용자는 과도한 인간의 개입 없이 농산물을 판매하여 수익을 올리기 위해 제품을 쉽게 추가할 수 있습니다. 처음에 앱은 Rootstock의 테스트넷에서 테스트되었고, 거의 프로덕션 준비 상태입니다(Rootstock의 메인넷으로 전환하기 위해 사소한 조정만 필요했습니다). 프로젝트는 이미 GitHub에 업로드되었으므로 리포지토리를 복제하여 직접 테스트할 수 있습니다. 이를 위해 저는 의 선호합니다. 하지만 이 튜토리얼에서는 모든 사용자가 튜토리얼을 단계별로 이해하기 쉽게 dApp을 빌드할 수 있도록 심층적으로 안내하려고 합니다. GitHub 저장소에서 프런트엔드 코드를 다운로드하여 적절한 디렉토리에 추가하는 것이 좋습니다. 프로젝트 설정부터 스마트 계약 배포, 실시간 기능이 있는 대화형 프런트엔드 생성까지 모든 것을 다룰 것입니다. GitHub Readme.md 시작하기에 앞서, 우리는 AgriMarket이라는 dApp을 구축할 계획이며, 이는 다음과 같은 기능을 갖출 것으로 기대됩니다. 지원되는 지갑(이 경우 MetaMask)을 통해 사용자가 Web3 기능에 액세스할 수 있도록 합니다. 사용자는 지갑을 dApp에 연결하여 농산물과 가격을 추가할 수 있습니다. 앱은 MetaMask와 상호 작용하여 스마트계약 호출을 확인합니다. 사용자는 장바구니에 제품을 추가할 수 있으며, dApp은 장바구니에 여러 제품이 있는 경우에도 거래를 시작할 수 있습니다. 사용자는 장바구니와 제품 목록 페이지 모두에서 실시간 알림, 거래 영수증, 제품 삭제 기능을 받을 수 있습니다. 📥필수 구성 요소 - 시작하기 전에 컴퓨터에 다음이 설치되어 있는지 확인하세요. Node.js (v14 이상) npm 또는 yarn 스마트 계약 개발을 위한 Truffle 또는 Hardhat RSK 테스트넷에 대해 구성된 MetaMask 확장 버전 제어를 위한 Git VSCode와 같은 IDE 📥프로젝트 설정 👉프로젝트 디렉토리 생성 전체 개발 및 테스트 프로세스 동안 이 주요 프로젝트 디렉토리를 선호하도록 설정해 주시기 바랍니다. 👉프로젝트 디렉토리 초기화 터미널에서 다음 명령을 실행하여 프로젝트에 대한 새 디렉토리를 만듭니다. mkdir rsk-agri-marketplace cd rsk-agri-marketplace 👉새로운 npm 프로젝트 초기화: npm init -y 👉Truffle 프로젝트 초기화 Truffle을 사용하여 스마트 계약을 컴파일하고 개발하므로 루트 디렉토리를 통해 초기화합니다. truffle init 이렇게 하면 기본 구조가 생성됩니다. • - • - • - • - contracts/ Solidity 계약 포함 migrations/ 배포 스크립트 test/ 계약 테스트 truffle-config.js Truffle 구성 파일 📥환경 변수 구성 개인 키, Pimata API 키 등의 민감한 정보는 .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 추가 공백이나 문자 불일치 없이 파일을 만드십시오. 그렇지 않으면 나중에 어려움을 겪게 됩니다. 나중에 스마트 계약을 업데이트하기 때문에 이 기억하십시오. 에서 Pinata API를 받으십시오. .env 단계를 여기 📥RSK 테스트넷에 연결하기 👉truffle-config.js 업데이트 프로젝트 디렉토리에서 이미 생성된 truffle-config.js를 볼 수 있습니다. 코드를 업데이트하여 RSK 테스트넷과 상호 작용할 수 있도록 하세요. 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 👉 디렉토리에 만듭니다. 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(); } } 👉migrations 에 마이그레이션 스크립트 작성 migrations/2_deploy_contracts.js const Marketplace = artifacts.require("Marketplace"); module.exports = function (deployer) { deployer.deploy(Marketplace); }; 👉계약 컴파일 및 배포 터미널을 통해 계약을 컴파일하려면 다음 코드를 실행하세요. truffle compile 모든 것이 올바르게 진행되면 터미널에서 다음과 같은 내용을 볼 수 있습니다. 터미널에서 다음 명령을 실행하여 Rootstock의 테스트넷에 배포합니다. Marketplace.sol truffle migrate --network rskTestnet 계약을 배포하기 전에 지갑에 일정량의 tRBTC가 필요합니다. RSK faucet에서 받으세요. 여기 프로세스가 성공적으로 완료되면 다음 터미널에 메시지가 표시됩니다. 에서 파일을 찾을 수 있습니다. 기억하세요, 이 파일을 다른 디렉토리로 복사하세요. \build\contracts\Marketplace.json Marketplace.json 마켓플레이스 dApp을 위한 프런트엔드 개발 이제 스마트 계약을 배포했으므로 사용자가 상호 작용할 수 있는 매력적인 마켓플레이스 프런트엔드를 구축할 것입니다. 프런트엔드에는 제품 목록, 제품 추가, 구매, 카트에 제품 추가/제거, 거래 추적, 알림 및 진행률 표시줄과 같은 실시간 피드백 제공과 같은 기능이 있습니다. 📥프런트엔드 개발 👉React 애플리케이션 초기화 프런트엔드에는 React를 사용합니다. 프로젝트 디렉토리에서 새로운 React 앱을 초기화합니다. npx create-react-app client 클라이언트 디렉토리로 이동합니다. cd client UI를 위해 Web3 및 Bootstrap 설치 npm install web3 bootstrap 👉프로젝트 구조 그림 1과 같은 프런트엔드 구조가 필요합니다. 👉src 에서 Web3 설정 src/utils/Marketplace.json 스마트 계약과 상호작용하려면 ABI(Application Binary Interface)를 가져와야 합니다. Truffle 디렉토리에서 ABI를 에서 언급한 대로 폴더로 복사합니다. build/contracts Marketplace.json 1단계 client/src/utils/ Web3 설정은 파일에 있습니다. 에서 다운로드하여 그림 1과 같이 적절한 디렉토리에 넣으세요. App.js GitHub 👉 실시간 알림 및 진행률 표시줄 실시간 알림을 위해 라이브러리와 유사한 통합할 것입니다. 진행률 표시줄에는 사용할 수도 있습니다. react-toastify react-bootstrap 디렉토리에 React Toastify를 설치하세요 client npm install react-toastify 👉 HTTP 요청(Pinata의 API)을 위해 Axios 설치: npm install axios 좋습니다. 이제 클라이언트 폴더(폴더+파일 포함)에서 모든 프런트엔드 구성 요소를 다운로드하세요. 그리고 적절한 디렉토리에 넣으세요. GitHub 저장소의 📥마지막 작업 및 앱과의 상호 작용 👉이제 dApp과 상호 작용할 수 있습니다. 터미널에서 다음 명령을 사용하여 React 앱을 실행할 수 있습니다. npm start 기본 브라우저가 자동으로 열립니다. MetMask 브라우저 확장 프로그램이 설치되었고 RSK 테스트넷이 제대로 구성되었는지 확인하세요( 프로젝트 가이드를 따라 올바른 네트워크를 선택할 수 있습니다). 여기서 이제 React 앱이 MetaMask 지갑 확장 프로그램을 호출합니다. 호출을 확인하세요. 그러면 다음 그림과 같이 메인 인터페이스에 연결된 지갑이 표시됩니다. 프런트엔드는 여러분에게 많은 기능을 제공합니다. 여러분은 제품을 추가/제거할 수 있습니다. 매번, 여러분은 MetaMask 지갑 확장 프로그램에서 전화를 확인하라는 요청을 받게 될 것입니다. 다음 gif를 확인하세요: 글쎄요, 이제 dApp이 카트에 추가된 거래를 제대로 처리하는지 테스트할 수 있습니다. "거래 내역" 섹션에서 모든 기술적 세부 정보와 함께 자세한 거래 내역을 볼 수 있습니다. 구매가 완료되면, dApp에 제품을 추가한 소유자에게 자금이 전송됩니다. 함께 앱을 테스트해 보겠습니다. 축하합니다! RSK 테스트넷에서 dApp을 성공적으로 개발하고 테스트했습니다. 원하는 기능을 추가하여 RSK 메인넷으로 전환할 수 있습니다. 테스트넷이 언급된 곳마다 코드를 조정하고 프로덕션에 적합한 앱을 빌드하기 위해 서두르고 있다면 여기에서 확인하세요. 프로젝트 문서를 📥잠재적 과제 및 미래: 제품 배달, 픽업 등 여러 프로세스를 포함하는 농업 시장을 시작하는 새로운 접근 방식이 될 것입니다. 구매자와 판매자를 자세히 알지 못하면 신뢰 문제가 발생할 수 있습니다. 또 다른 과제는 아직 실험 단계에 있으며, 소비자가 이 진화하는 기술에 어떻게 반응하는지 알 수 없다는 것입니다. 따라서 교육과 훈련은 농부와 소비자 모두에게 새로운 기술을 도입하는 데 필수적입니다. 또한 충분한 협업은 농산물에 대한 지속 가능한 분산형 시장을 개발하는 데 중요한 요소입니다. 결론: 우리는 Rootstock(RSK) 테스트넷에서 분산형 농업 시장을 성공적으로 구축했습니다. 보안이 최우선으로 고려되었기 때문에 OpenZeppelin 계약을 사용하여 스마트 계약 코드를 보호하기 위한 여러 가지 조치를 취했습니다. 테스트된 dApp은 간단한 분산형 시장에 필요한 거의 모든 기능을 갖추고 있지만 Rootstock의 메인넷에서 앱을 출시할 계획이라면 더 많은 기능으로 강화할 수 있습니다. 또한 모든 것이 의도한 대로 원활하게 작동하는지 확인하기 위해 보안을 염두에 두십시오. 우리는 모든 거래를 진행하기 위해 낮은 거래 수수료와 함께 Rootstock의 빠른 거래 처리 기능을 활용하려고 시도했으며, 이는 비트코인의 악명 높은 혼잡 문제를 해결할 것입니다. 물론, 이런 종류의 분산형 마켓플레이스는 많은 문제에 직면해야 하지만, 우리가 자연스럽게 자유를 추구함에 따라, 우리는 미래에 더욱 분산형 마켓플레이스를 찾을 수 있기를 바랄 수 있습니다.