このため、私はのReadme.md
好みます。ただし、このチュートリアルでは、あらゆる種類のユーザーがチュートリアルを段階的に理解しながら簡単に dApp を構築できるように、詳細にガイドします。GitHub リポジトリからフロントエンド コードをダウンロードし、適切なディレクトリに追加することをお勧めします。プロジェクトのセットアップからスマート コントラクトのデプロイ、リアルタイム機能を備えたインタラクティブなフロントエンドの作成まで、すべてをカバーします。
mkdir rsk-agri-marketplace cd rsk-agri-marketplace
npm init -y
truffle init
これにより、基本的な構造が作成されます。 • contracts/
- Solidity コントラクトが含まれます• migrations/
-デプロイメント スクリプト• test/
-コントラクトのテスト• truffle-config.js
- Truffle 構成ファイル
npm install dotenv
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=//public-node.testnet.rsk.co REACT_APP_CONTRACT_ADDRESS=Contract Address
余分なスペースや文字の不一致のない.env
ファイルを作成してください。そうしないと、後で問題が発生します。後でスマート コントラクトを更新するので、この手順を覚えておいてください。Pinata API はから取得してください。
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: `//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, }, };
npm install @truffle/hdwallet-provider
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
Marketplace.json
ファイルは\build\contracts\Marketplace.json
にあります。覚えておいてください。このファイルを別のディレクトリにコピーします。
npx create-react-app client
cd client
npm install web3 bootstrap
👉src src/utils/Marketplace.json
での Web3 セットアップ
build/contracts
ディレクトリからMarketplace.json
ABI をclient/src/utils/
フォルダにコピーします。
App.js
ファイルにあります。これをからダウンロードし、図 1 に示すように適切なディレクトリに配置します。
リアルタイム通知のために、 react-toastify
のようなライブラリを統合します。プログレスバーにはreact-bootstrap
使用することもできます。
client
ディレクトリにReact Toastifyをインストールする
npm install react-toastify
npm install axios
npm start