🍏

web3.jsでデプロイしたコントラクトをReactで使う(前編)

2021/08/04に公開

はじめに

今回はデプロイしたコントラクトを実際にwebアプリで扱う方法を紹介したいと思います。(いわゆるDAppと呼ばれるもの)
コントラクトは簡単なものを使用して、web3.jsの使い方にフォーカスを当てたいと思います。
ちなみにフロントはReactを使っていますので、create-react-appでReactが使える準備だけお願いします。

準備

デプロイしたコントラクト

Greeting.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.21 <0.7.0;

contract Greeting {
    string public greeting = "hello";
    
    // greetingを読むだけの関数。初期値は"hello"。
    function sayHello() external view returns (string memory) {
        return greeting;
    }
    // 今のgreetingを編集する関数。編集するのでガス代が発生する。
    function updateGreeting(string calldata _greeting) external {
        greeting = _greeting;
    }
}

コントラクトのデプロイ方法は前回の記事をご参考ください。

プロバイダ

ブロックチェーンはノードによって成り立っているので、web3.jsのプロバイダ設定ではどのノードにアクセスして処理を実行させるかを設定します。

App.js
const web3 = new Web3(
  new Web3.providers.HttpProvider(
    "https://ropsten.infura.io/v3/YOUR_INFURA_PROJECT_ID"
  )
);

今回はinfuraを使用してRopstenにデプロイしたコントラクトを使用しますので、HttpProviderの中はinfuraのURLを書いてあげます。もしganacheを使ってローカルにデプロイした場合はhttp://localhost:7545になるかと思います。

コントラクトのアドレス

コントラクトをデプロイすると、そのコントラクトのアドレスが割り振られるので、アドレスをコピーしておきます。

App.js
const address = "0x4D564C434CfeC2AD44C9012bAD771b315C2738aA";

ABI(Application Binary Interface)

コントラクトのメソッドをJSON形式で表しているものです。
コントラクトをcompileした際に生成されます。

App.js
import ABI from "./contracts/Greeting.json";
const abi = ABI.abi;

srcの中にcontractsフォルダを作り、生成されたコントラクトのJSONファイルをそのままコピーして入れましょう。
あとはabi部分を呼び出してあげるだけです。

コントラクトの呼び出し方

これでデプロイしたコントラクトを呼び出す準備ができました。

App.js
const contract = new web3.eth.Contract(abi, address);

今の段階の全体のコードはこんな感じです。

App.js
import "./App.css";
import Web3 from "web3";
import ABI from "./contracts/Greeting.json";

const web3 = new Web3(
  new Web3.providers.HttpProvider(
    "https://ropsten.infura.io/v3/YOUR_INFURA_PROJECT_ID"
  )
);
const address = "0x4D564C434CfeC2AD44C9012bAD771b315C2738aA";
const abi = ABI.abi;
const contract = new web3.eth.Contract(abi, address);

function App() {
  return (
    <div className="App">
      <h1>How to use web3.js</h1>
    </div>
  );
}
export default App;

ではコントラクトを呼んでみようと思います。

call

上記のGreetingコントラクトの一つ目の関数、sayHello()はview関数を使用していますので、読み取り専用になります。読み取り専用ということは、関数を実行するのにガス代もかかりません。
読み取り専用の関数(view関数やpure関数)にはcallを使って呼ぶことができます。

App.js
const handleCall = async () => {
    const greeting = await contract.methods.sayHello().call();
    console.log(greeting);
  };
 return (
    <div className="App">
      <h1>How to use web3.js</h1>
      <button onClick={handleCall}>sayHello</button>
    </div>
  );

コントラクトの関数を使用すると戻り値がPromiseで返ってくるので、async/awaitを使用しています。コントラクトでgreeting="hello"にしていれば、console.logでhelloが表示されていると思います。

続きます

少し長くなりそうなので今回の記事はここまでにします。
次回は二つ目の関数、updateGreetingで実際にブロックチェーン上のデータを変更する実装を説明したいと思います。ガス代もかかるので、Metamaskも使用します。

Discussion