第11章Webアプリケーション開発
LINK TO LEARNING学びを広げるリンク
Solidity is a high-level, object-oriented language used to implement smart contracts. Influenced by JavaScript, C++, and Python, Solidity is focused on the Ethereum Virtual Machine. Smart contracts implemented by Solidity are used for purposes like blind auctions, voting, and crowdfunding. Visit this page on Solidity (https://openstax.org/r/76Solidity) to learn more.
英語のヒント
Solidityは、スマートコントラクトの実装に使う、高水準のオブジェクト指向言語である。JavaScript、C++、Pythonの影響を受け、Ethereum Virtual Machineを中心にしている。Solidityで実装したスマートコントラクトは、非公開入札のオークション、投票、クラウドファンディングなどに使われる。詳しくは、Solidityのこのページ(https://openstax.org/r/76Solidity)を参照。
Creating the Front-End React ComponentsフロントエンドのReactコンポーネントの作成
The TodoList component renders the user interface for the Todo app. In the ethreact/src/ directory, create the components/ directory. In the components/ directory, create the file TodoList.js and then create the TodoList component.
TodoListコンポーネントは、Todoアプリの利用者インターフェースを描画する。ethreact/src/ディレクトリにcomponents/ディレクトリを作り、その中にTodoList.jsファイルを作成して、TodoListコンポーネントを作る。
import React, { Component } from 'react'
class TodoList extends Component {
render() {
return (
<div id="content"> <form onSubmit={(event) => {
event.preventDefault() this.props.createTask(this.task.value)
}}> <input id="newTask" ref={(input) => {
this.task = input }} type="text"
className="form-control" placeholder="Add task..."
required /> <input type="submit" hidden={true} />
</form> <ul id="taskList" className="list-unstyled"> {
this.props.tasks.map((task, key) => { return( <div
className="taskTemplate" className="checkbox" key={key}> <label>
<input type="checkbox"
name={task.id} defaultChecked={task.completed}
ref={(input) => { this.checkbox = input
}} onClick={(event) => {
this.props.toggleCompleted(this.checkbox.name) }}/>
<span className="content">{task.content}</span>
</label> </div> ) })}
</ul> <ul id="completedTaskList" className="list-unstyled">
</ul> </div>
);
}
}
export default TodoList;Update the ethreact/src/App.js to import and render the TodoList component.
ethreact/src/App.jsを更新し、TodoListコンポーネントをインポートして描画する。
render() {
return (
<div> <nav className="navbar navbar-dark fixed-top bg-dark flex-md-nowrap p-0 shadow"> <a className="navbar-brand col-sm-3 col-md-2 mr-0"
href="#">ToDo</a> <ul className="navbar-nav px-3"> <li
className="nav-item text-nowrap d-none d-sm-none d-sm-block"> <small><a
className="nav-link" href="#"><span id="account"></span></a></small> </li>
</ul> </nav> <div className="container-fluid"> <div
className="row"> <main role="main" className="col-lg-12 d-flex justify-content-center"> { this.state.loading ? <div id="loader"
className="text-center"><p className="text-center">Loading...</p></div>
: <TodoList tasks={this.state.tasks}
createTask={this.createTask}
toggleCompleted={this.toggleCompleted} /> }
</main> </div> </div> </div>
);
}Adding Web3 to the React AppReactアプリへのWeb3の追加
The next step is to add Web3 and configure it to connect to Ganache. To do this, open ethreact/src/App.js, import the Web3 package, and add the code shown here. In this code, a web3 connection is instantiated providing the Ganache URL (http://localhost:8545). This enables the React app to connect to the blockchain. The blockchain account information is then accessed and added to the React app’s state object. In the ethreact/src/ directory, create the file getWeb3.js and add the code shown. This code creates a Web3 object via different connection approaches depending on the approach used (e.g., type of DApp browser, using localhost).
英語のヒント
次に、Web3を追加し、Ganacheへ接続するよう設定する。そのために、ethreact/src/App.jsを開き、Web3パッケージをインポートして、次のコードを追加する。このコードは、GanacheのURL(http://localhost:8545)を与えてweb3接続をインスタンス化する。これにより、Reactアプリはブロックチェーンへ接続できる。その後、ブロックチェーンのアカウント情報にアクセスし、Reactアプリのstateオブジェクトへ追加する。ethreact/src/ディレクトリにgetWeb3.jsファイルを作り、示されたコードを追加する。このコードは、使う方法(DAppブラウザーの種類、localhostの使用など)に応じた、異なる接続手段を通じて、Web3オブジェクトを作成する。
import Web3 from "web3";
const getWeb3 = () =>
new Promise((resolve, reject) => {
// Wait for loading completion to avoid race conditions with web3 injection timing.
window.addEventListener("load", async () => {
// Modern dapp browsers...
if (window.ethereum) {
const web3 = new Web3(window.ethereum);
try {
// Request account access if needed
await window.ethereum.enable();
// Accounts now exposed
resolve(web3);
} catch (error) {
reject(error);
}
}
// Legacy dapp browsers...
else if (window.web3) {
// Use Mist/MetaMask's provider.
//const web3 = window.web3; // ORIG
const web3 = window.web3.currentProvider.enable()
console.log("Injected web3 detected.");
resolve(web3);
}
// Fallback to localhost; use dev console port by default...
else {
const provider = new Web3.providers.HttpProvider(
"http://127.0.0.1:8545"
);
const web3 = new Web3(provider);
console.log("No web3 instance injected, using Local web3.");
resolve(web3);
}
});
});
export default getWeb3;Configuring the React App to Communicate with the Smart Contractスマートコントラクトと通信するためのReactアプリの設定
To make the tasks from the smart contract available to the React app, create a config file, along with the contract address and ABI. To do this, in the ethreact/src/ directory, create the file config.js. Then, create two variables: TODO_LIST_ADDRESS and TODO_LIST_ABI. Grab the contract address that was provided when the smart contract was deployed to the blockchain and assign it to TODO_LIST_ADDRESS. Open the ethreact/build/ contracts/TodoList.json file and copy the ABI portion only and assign it to TODO_LIST_ABI.
英語のヒント
スマートコントラクトのタスクをReactアプリで使えるようにするため、コントラクトのアドレスとABIを含む設定ファイルを作成する。ethreact/src/ディレクトリにconfig.jsファイルを作り、TODO_LIST_ADDRESSとTODO_LIST_ABIの2つの変数を作成する。スマートコントラクトをブロックチェーンへ配置した際に出力されたコントラクトのアドレスを取得し、TODO_LIST_ADDRESSへ代入する。ethreact/build/contracts/TodoList.jsonファイルを開き、ABIの部分だけをコピーして、TODO_LIST_ABIへ代入する。
export const TODO_LIST_ADDRESS = '0x9A93A9951c1cAcF0Cecc320Fa6aD4e05d55a2d02'
export const TODO_LIST_ABI = [
{
"inputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "id",
"type": "uint256"
},
{
"indexed": false,
"internalType": "bool",
"name": "completed",
"type": "bool"
}
],
"name": "TaskCompleted",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "id",
"type": "uint256"
},
{
"indexed": false,
"internalType": "string",
"name": "content",
"type": "string"
},
{
"indexed": false,
"internalType": "bool",
"name": "completed",
"type": "bool"
}
],
"name": "TaskCreated",
"type": "event"
},
{
"constant": true,
"inputs": [],
"name": "taskCount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "tasks",
"outputs": [
{
"internalType": "uint256",
"name": "id",
"type": "uint256"
},
{
"internalType": "string",
"name": "content",
"type": "string"
},
{
"internalType": "bool",
"name": "completed",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "string",
"name": "_content",
"type": "string"
}
],
"name": "createTask",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"internalType": "uint256",
"name": "_id",
"type": "uint256"
}
],
"name": "toggleCompleted",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
]Next, update
ethreact/src/App.js. Import getWeb3.js and add the following code to the componentDidMount() life cycle method. This will connect to the blockchain network and load the contract before the React components renders in the browser.次に、ethreact/src/App.jsを更新する。getWeb3.jsをインポートし、componentDidMount()ライフサイクルメソッドに次のコードを追加する。これによって、Reactのコンポーネントがブラウザー内で描画される前に、ブロックチェーンネットワークへ接続し、コントラクトを読み込む。
componentDidMount = async () => {
try {
// Get network provider and web3 instance.
const web3 = await getWeb3();
// Use web3 to get the user's accounts.
const accounts = await web3.eth.getAccounts();
// Get the contract instance.
const networkId = await web3.eth.net.getId();
let deployedNetwork = TodoListABI.networks[networkId];
const todoListInstance = new web3.eth.Contract(
TODO_LIST_ABI,
deployedNetwork && deployedNetwork.address
);
// Set web3, accounts, and contract to the state, and then proceed with an
// example of interacting with the contract's methods.
this.setState({ web3, accounts, todoListContract: todoListInstance },
this.runExample);
} catch (error) {
// Catch any errors for any of the above operations.
alert(
'Failed to load web3, accounts, or contract. Check console for details.',
);
console.error(error);
}
};Launch the React app by running the following command:
次のコマンドを実行し、Reactアプリを起動する。
$npm startLaunch a browser with the MetaMask plug-in installed and navigate to http://localhost:3000. Create a task.
MetaMaskプラグインをインストールしたブラウザーを起動し、http://localhost:3000へ移動する。タスクを作成する。