テクノロジーは人類に奉仕するものでなければなりません。すでに多くの分野に革命を起こしているブロックチェーン技術は、農業分野にも変革をもたらす可能性があります。この分散型テクノロジーを主流の採用トレンドにするには、一般大衆に届くように簡素化し、より幅広いユーザーに浸透させて、最終的に使用例を増やす必要があります。
このチュートリアルでは、ユーザーが Rootstock (RSK) ブロックチェーン ネットワーク上で農産物を売買できる分散型アプリケーション (dApp) を構築します。主な目的は、ブロックチェーン ネットワーク上で実行される dApp を構築することです。あらゆる種類のユーザーが、過度の人的介入なしに農産物を販売して収益を得るために、簡単に製品を追加できます。
当初、アプリは Rootstock のテストネットでテストされており、ほぼ本番環境対応の状態です (Rootstock のメインネットに切り替えるために若干の調整が必要でした)。プロジェクトはすでに GitHub にアップロードされているため、リポジトリをクローンして自分でテストすることができます。
このため、私はGitHubのReadme.md
好みます。ただし、このチュートリアルでは、あらゆる種類のユーザーがチュートリアルを段階的に理解しながら簡単に dApp を構築できるように、詳細にガイドします。GitHub リポジトリからフロントエンド コードをダウンロードし、適切なディレクトリに追加することをお勧めします。プロジェクトのセットアップからスマート コントラクトのデプロイ、リアルタイム機能を備えたインタラクティブなフロントエンドの作成まで、すべてをカバーします。
始める前に、私たちは以下の機能を持つと予想される AgriMarket という dApp の構築を目指しています。
👉プロジェクトディレクトリを作成する
開発およびテストのプロセス全体を通じて、このメイン プロジェクトのディレクトリを優先するようにしてください。
👉プロジェクトディレクトリを初期化する
ターミナルで次のコマンドを実行して、プロジェクト用の新しいディレクトリを作成します。
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
余分なスペースや文字の不一致のない.env
ファイルを作成してください。そうしないと、後で問題が発生します。後でスマート コントラクトを更新するので、この手順を覚えておいてください。Pinata API はここから取得してください。
👉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(); } }
👉migrates 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
にあります。覚えておいてください。このファイルを別のディレクトリにコピーします。
マーケットプレイス dApp のフロントエンド開発
スマート コントラクトをデプロイしたので、ユーザーがマーケットプレイスとやり取りできる魅力的なフロントエンドを構築します。フロントエンドには、製品リスト、製品の追加、購入、カートへの製品の追加/削除、トランザクションの追跡、通知や進行状況バーなどのリアルタイム フィードバックの提供などの機能があります。
👉Reactアプリケーションを初期化する
フロントエンドにはReactを使用します。
プロジェクト ディレクトリで新しい React アプリを初期化します。
npx create-react-app client
クライアント ディレクトリに移動します。
cd client
UI用にWeb3とBootstrapをインストールする
npm install web3 bootstrap
👉プロジェクト構造
図 1 に示すように、フロントエンドの構造が必要になります。
👉src src/utils/Marketplace.json
での Web3 セットアップ
スマート コントラクトと対話するには、ABI (アプリケーション バイナリ インターフェイス) をインポートします。
build/contracts
ディレクトリからMarketplace.json
ABI をclient/src/utils/
フォルダにコピーします。
App.js
ファイルにあります。これをGitHubからダウンロードし、図 1 に示すように適切なディレクトリに配置します。
👉 リアルタイム通知と進捗バー
リアルタイム通知のために、 react-toastify
のようなライブラリを統合します。プログレスバーにはreact-bootstrap
使用することもできます。
client
ディレクトリにReact Toastifyをインストールする
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 メインネットに切り替えることができます。テストネットが言及されているコードを調整するだけで、本番環境対応のアプリを急いで構築する場合は、ここにあるプロジェクトのドキュメントも確認してください。
これは、製品の配送、ピックアップなどのいくつかのプロセスを含む農業市場を開始するための新しいアプローチになります。買い手と売り手の詳細を知らなければ、信頼の問題が生じる可能性があります。もう 1 つの課題は、まだ実験段階であり、進化するこの技術に対して消費者がどのように反応するかがわからないことです。
したがって、農家と消費者の両方が新しい技術を採用するには、教育とトレーニングが不可欠です。また、十分な協力関係は、農産物の持続可能な分散型市場を開発するための重要な要素です。
Rootstock (RSK) テストネット上に分散型農業マーケットプレイスを構築することに成功しました。セキュリティを最優先に考え、OpenZeppelin 契約を使用してスマートコントラクト コードを保護するための対策を講じています。テスト済みの dApp には、シンプルな分散型マーケットプレイスに必要なほぼすべての機能が含まれていますが、Rootstock のメインネットでアプリを起動する予定がある場合は、さらに多くの機能を追加して強化できます。また、すべてが意図したとおりにスムーズに機能するように、セキュリティにも留意してください。
私たちは、すべての取引を進めるために、取引手数料が低い Rootstock の高速取引処理機能を活用しようと試みました。これにより、ビットコインの悪名高い混雑問題が解決されます。もちろん、このような分散型マーケットプレイスには多くの問題が伴いますが、私たちは当然自由を求めているので、将来的にはより分散化されたマーケットプレイスが見つかると期待できます。