以太坊DApp開発-無知から門を見つけるまで


目次


文書ディレクトリ

  • ディレクトリ
  • ゼロ、関連ツール
  • 0.1ローカルテストノード
  • 0.2 MetaMask
  • 0.3 Remixの使用
  • 一、テンプレートプロジェクトテスト
  • 1.1初期化項目
  • 1.2コンパイル契約
  • 1.3導入契約
  • 1.3.1 ganache
  • を起動
  • 1.3.2 truffle-configを修正する.js
  • 1.3.3導入
  • 1.4テスト
  • 1.4.1 Remixでのテスト
  • 1.4.2 Reactプロジェクトを起動してテスト
  • を行う
  • 二、DIY
  • 2.1修正項目&コンパイル契約
  • 2.2導入契約
  • 2.3 React項目を修正
  • 関連接続
  • ゼロ、関連ツール


    本明細書で直接使用するツール:Remix,truffle(v 5.1.0)、ganache(v 2.1.2)、MetaMaskなど

    0.1ローカルテストノード

  • testrpc:nodejsパッケージ、コマンドラインツールですが、新版のsolidityのサポート度は高くなく、契約の導入時にVM Exceptionなどの異常
  • を報告します.
  • ganache-cli:nodejsパッケージ、コマンドラインツール
  • ganache:インタフェースツール、比較的便利
  • 0.2 MetaMask


    Chromeプラグイン.異なるノードを接続することを選択できます.ユーザー秘密鍵をインポートした後、ユーザーのEthernet通貨の数を表示することもできます.関連口座後に一部の取引が発生した場合、ポップアップウィンドウを開いてユーザーに取引を確認させることができます.

    0.3 Remixの使用


    Remix: http://remix.ethereum.org File explorersでは新規契約の作成、契約の編集などの操作ができます.Solidity compilerでSolidityコンパイラバージョンを選択し、まずコンパイルして文法に問題があるかどうかを検証し、Deploy & run transactionsで環境を選択します.Environment選択Injected Web3はnetmaskプラグインをポップアップしてアカウントバインドを行います(EnvironmentはWeb 3 Providerも選択できます.エーテル坊ノードに接続するように提示されます.localhost:8545に接続してテストすることができます.)Deploy & run transactionsパネルの契約選択ドロップダウンボックスの下にはDeployとAt Addressがあり、前者はコンストラクション関数で契約を作成し、後者は契約のアドレスを入力して取得します(接続?)契約は、作成(/接続)に成功すると、契約で呼び出す方法が下に表示され、このパネルで契約を呼び出す関数を操作できます(アドレス接続の契約を入力することで、口座などの情報を構成して取引を実行する必要があります).
    契約作成ウィンドウの下にはコンソールがあり、Web 3のAPIを介して命令を実行することができる.eth.getBalance(“0x04555018d100bd9ad75544de623ec8e3692e423a”);

    一、テンプレート項目テスト


    1.1プロジェクトの初期化

    # truffle unbox react
    ✔ Preparing to download
    ✔ Downloading
    ✔ Cleaning up temporary files
    ......
    ✔ Setting up box
    
    Unbox successful. Sweet!
    
    Commands:
    
      Compile:              truffle compile
      Migrate:              truffle migrate
      Test contracts:       truffle test
      Test dapp:            cd client && npm test
      Run dev server:       cd client && npm run start
      Build for production: cd client && npm run build
    

    (直接ダウンロードは遅く、プロキシダウンロードを考慮)実行コマンドtruffle unbox reactはテンプレートアイテムをダウンロードします.ここでclientディレクトリの下にはReactプロジェクトがあり、Setting up boxまで実行すると、client/node_で時間がかかります.modulesディレクトリの下で必要な依存度(100+MB)をダウンロードします.
    TRUFFLE BOXESでboxの名前を検索してダウンロードすることもできます.https://www.trufflesuite.com/boxes/react、ダウンロードボタンをクリックしてダウンロードできますが、クライアントディレクトリにnode_がありません.modules、依存問題を自分で解決する必要があります.
    truffleのWebサイトから直接ダウンロードされるプロジェクトディレクトリの構造は、次のとおりです.
    .
    ├── box-img-lg.png
    ├── box-img-sm.png
    ├── client
    │   ├── package.json
    │   ├── package-lock.json
    │   ├── public
    │   │   ├── favicon.ico
    │   │   ├── index.html
    │   │   ├── logo192.png
    │   │   ├── logo512.png
    │   │   ├── manifest.json
    │   │   └── robots.txt
    │   ├── README.md
    │   ├── src
    │   │   ├── App.css
    │   │   ├── App.js
    │   │   ├── App.test.js
    │   │   ├── getWeb3.js
    │   │   ├── index.css
    │   │   ├── index.js
    │   │   ├── logo.svg
    │   │   └── serviceWorker.js
    │   └── yarn.lock
    ├── contracts
    │   ├── Migrations.sol
    │   └── SimpleStorage.sol
    ├── LICENSE
    ├── migrations
    │   ├── 1_initial_migration.js
    │   └── 2_deploy_contracts.js
    ├── README.md
    ├── test
    │   ├── simplestorage.js
    │   └── TestSimpleStorage.sol
    ├── truffle-box.json
    └── truffle-config.js
    

    1.2契約のコンパイル

    root@kali:/BlockChain/react-box-master# truffle compile
    
    Compiling your contracts...
    ===========================
    > Compiling ./contracts/Migrations.sol
    > Compiling ./contracts/SimpleStorage.sol
    > Artifacts written to /BlockChain/react-box-master/client/src/contracts
    > Compiled successfully using:
       - solc: 0.5.12+commit.7709ece9.Emscripten.clang
    

    プロジェクトディレクトリの下でtruffle compileを実行してコンパイルし、コンパイル後にclient/src/contractsディレクトリを生成し、このディレクトリの下に2つのファイルがあります:Migrations.json SimpleStorage.json

    1.3導入契約


    1.3.1 ganacheの起動


    1.3.2 truffle-configを修正する.js


    ノード情報を設定します.変更されたファイルの内容は次のとおりです.
    const path = require("path");
    
    module.exports = {
      // See 
      // to customize your Truffle configuration!
      contracts_build_directory: path.join(__dirname, "client/src/contracts"),
      networks: {
        development: {
          host: "localhost",
          port: 8545,
          network_id: "*"
        }
      }
    };
    

    1.3.3配置

    truffle migrateを使用して導入:
    root@kali:/BlockChain/react-box-master# truffle migrate
    
    Compiling your contracts...
    ===========================
    > Everything is up to date, there is nothing to compile.
    
    
    
    Starting migrations...
    ======================
    > Network name:    'development'
    > Network id:      5777
    > Block gas limit: 0x6691b7
    
    
    1_initial_migration.js
    ======================
    
       Deploying 'Migrations'
       ----------------------
       > transaction hash:    0x872c9be81fc25005dc3535821e9fe52375b0ccb409cbdf4b85e2483d76bbcfe0
       > Blocks: 0            Seconds: 0
       > contract address:    0xe7536a28473dFF0875b81bDdb7dCe10CA1e95cDe
       > block number:        1
       > block timestamp:     1574910360
       > account:             0xA5D2948e8fd43D6d0C8eD7bCe0fEba3039A8D009
       > balance:             99.99472518
       > gas used:            263741
       > gas price:           20 gwei
       > value sent:          0 ETH
       > total cost:          0.00527482 ETH
    
    
       > Saving migration to chain.
       > Saving artifacts
       -------------------------------------
       > Total cost:          0.00527482 ETH
    
    
    2_deploy_contracts.js
    =====================
    
       Deploying 'SimpleStorage'
       -------------------------
       > transaction hash:    0xba46904f988290f25d36918c7f731f9d4bdb3d2b6b3c2520f2b79f90f0df5173
       > Blocks: 0            Seconds: 0
       > contract address:    0x0D7C49CFfD2e82B5C124F455fCEaDC27d1cdC41D
       > block number:        3
       > block timestamp:     1574910361
       > account:             0xA5D2948e8fd43D6d0C8eD7bCe0fEba3039A8D009
       > balance:             99.99173734
       > gas used:            107369
       > gas price:           20 gwei
       > value sent:          0 ETH
       > total cost:          0.00214738 ETH
    
    
       > Saving migration to chain.
       > Saving artifacts
       -------------------------------------
       > Total cost:          0.00214738 ETH
    
    
    Summary
    =======
    > Total deployments:   2
    > Final cost:          0.0074222 ETH
    
    

    1.4テスト


    1.4.1 Remixでのテスト


    オンラインIDEで契約をテストし、まずMetaMaskをganacheが起動したノードに接続し、そのうちの1つのテストアカウントをインポートします.SimpleStorage.solはRemix Solidity IDEにコピーしてコンパイルし、Deploy & run transactionsウィンドウで契約を選択し、At Addressボタンの後の入力ボックスに上記配置した契約アドレス0x0D7C49CFfD2e82B5C124F455fCEaDC27d1cdC41Dを入力し、ボタンをクリックして契約インスタンスを取得する.
    下に表示される契約メソッドのリストで、パラメータを入力してsetメソッド名を表示するボタンをクリックしてメソッドを呼び出し、MetaMaskウィンドウをポップアップし、取引を確認し、完了するとganacheにブロックが追加され、CONTRACT CALLのタイプの取引が表示されます.さらにオンラインIDEのページでgetメソッドをクリックすると、先ほど保存した値が返されます.

    1.4.2 Reactプロジェクトを起動してテストを行う


    client/src/App.jsにはReactコンポーネントが定義されており、ライフサイクルメソッドcomponentDidMountが呼び出されると、web 3、アカウント、契約インスタンスを取得し、ステータスを更新し、runExampleメソッドを呼び出す.runExampleメソッドでは、まず契約を呼び出すsetメソッドに値5を書き、契約のgetメソッドで書き込まれたばかりの値を取得し、取得した値をコンポーネントの状態に更新した後、コンポーネントのrenderメソッドが呼び出され、この値とHTMLがDOMにレンダリングされます.App.jsコードは以下の通りです.
    import React, { Component } from "react";
    import SimpleStorageContract from "./contracts/SimpleStorage.json";
    import getWeb3 from "./getWeb3";
    
    import "./App.css";
    
    class App extends Component {
      state = { storageValue: 0, web3: null, accounts: null, contract: null };
    
      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();
          const deployedNetwork = SimpleStorageContract.networks[networkId];
          const instance = new web3.eth.Contract(
            SimpleStorageContract.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, contract: instance }, 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);
        }
      };
    
      runExample = async () => {
        const { accounts, contract } = this.state;
    
        // Stores a given value, 5 by default.
        await contract.methods.set(5).send({ from: accounts[0] });
    
        // Get the value from the contract to prove it worked.
        const response = await contract.methods.get().call();
    
        // Update state with the result.
        this.setState({ storageValue: response });
      };
    
      render() {
        if (!this.state.web3) {
          return 
    Loading Web3, accounts, and contract...
    ; } return (

    Good to Go!

    Your Truffle Box is installed and ready.

    Smart Contract Example

    If your contracts compiled and migrated successfully, below will show a stored value of 5 (by default).

    Try changing the value stored on line 40 of App.js.

    The stored value is: {this.state.storageValue}
    ); } } export default App;
    await contract.methods.set(5).send({ from: accounts[0] });という行のコードを注釈し、クライアントディレクトリの下でnpm startを実行してサービスを開始し、ブラウザはlocalhost:3000にアクセスし、ページには前のステップでオンラインIDEから書き込まれた値が表示されます.

    二、DIY


    2.1プロジェクトの修正&契約のコンパイル


    テンプレートの項目について修正を行い、まず項目目次のcontracts目次の下に契約Votingを新規作成する.sol(あるチュートリアルからコピーされ、solidityバージョンに基づいて少し変更された簡単な投票契約):
    pragma solidity ^0.5.0;
    
    contract Voting {
    
        bytes32[] candidates;
        
        mapping(bytes32 => uint) candidatesVotingCount;
        
        // https://stackoverflow.com/questions/53460851/typeerror-data-location-must-be-memory-for-parameter-in-function-but-none-wa
        // google remix  bytes32[]  :https://blog.csdn.net/github_38575699/article/details/101269929
        //  remix solidity ?Deploy , , bytes32 32 
        // ["A", "B"] :
        /* ["0x4100000000000000000000000000000000000000000000000000000000000000", 
            "0x4200000000000000000000000000000000000000000000000000000000000000"]
        */
        constructor(bytes32[] memory _candidates) public {
            candidates = _candidates;
        }
        
        function votingToPerson(bytes32  person) public {
            assert(isValidToPerson(person));
            candidatesVotingCount[person] += 1;
        }
        
        function votingTotalToPerson(bytes32  person) view public returns(uint) {
            require(isValidToPerson(person));
            return candidatesVotingCount[person];
        }
        
        function isValidToPerson(bytes32  person) view public returns(bool) {
            for (uint i = 0; i < candidates.length; i++) {
                if (candidates[i] == person) {
                    return true;
                }
            }
            return false;
        }
    }
    

    その後truffle compileコンパイル契約を実行し、コンパイル完了後client/src/contractsは以前よりVoting.json増加した.

    2.2導入契約


    migrationsディレクトリの2_deploy_contracts.jsを変更し、その中のテンプレートプロジェクト契約名SimpleStorageをすべてVotingに変更し、truffle migrateの導入を実行し、エラーを報告します.
    ......
    Error: Error: Error:  *** Deployment Failed ***
    
    "Voting" -- Invalid number of parameters for "undefined". Got 0 expected 1!.
    
        at Object.run (/node-v12.13.0-linux-x64/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:92:1)
        at processTicksAndRejections (internal/process/task_queues.js:93:5)
    Truffle v5.1.0 (core: 5.1.0)
    Node v12.13.0
    

    いくつかの解決策(https://stackoverflow.com/questions/54304214/truffle-smart-contract-error-invalid-number-of-parameter)、2_deploy_contracts.jsのdeployer.deployは2番目のパラメータを伝えることができ、何回か試した後、2番目のパラメータが契約の構造関数のパラメータであることを発見し、2_deploy_contracts.jsの内容を以下のように修正した.
    var Voting = artifacts.require("./Voting.sol");
    
    module.exports = function(deployer) {
      deployer.deploy(Voting, ["0x4100000000000000000000000000000000000000000000000000000000000000", "0x4200000000000000000000000000000000000000000000000000000000000000"]);
    };
    

    その後、truffle migrateを使用して配備され、配備後、出力された契約アドレスに基づいてオンラインIDEでテストできるようになった.

    2.3 React項目の修正


    まずAppを保存します.jsをバックアップとして、Appを変更します.jsの内容は以下の通りです.
    import React, { Component } from "react";
    import Voting from "./contracts/Voting.json";
    import getWeb3 from "./getWeb3";
    
    import "./App.css";
    
    class App extends Component {
      state = {voting: [], web3: null, accounts: null, contract: null};
    
      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();
          const deployedNetwork = Voting.networks[networkId];
          const instance = new web3.eth.Contract(
            Voting.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, contract: instance}, this.getVoting);
        } 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);
        }
      };
    
      getVoting = async () => {
        const { contract } = this.state;
        let candidates = ["0x4100000000000000000000000000000000000000000000000000000000000000", "0x4200000000000000000000000000000000000000000000000000000000000000"];
        let voting = new Array();
        await Promise.all(candidates.map(async (elem, index) => {
          voting.push({
            name: elem,
            //  
            count: await contract.methods.votingTotalToPerson(elem).call(),
            key: index
          })
        }));
        this.setState({ voting});
      };
    
      render() {
        if (!this.state.web3) {
          return 
    Loading Web3, accounts, and contract...
    ; } return (

    Voting

    { this.state.voting.map((candidate) => { return (

    チケットを

    ) }) }
    ); } } export default App;

    クライアントディレクトリの下でコマンドnpm startでサービスを開始し、ブラウザからlocalhost:3000にアクセスすると、リストされた投票数が表示されます.ページ上の入力ボックスとボタンで投票することもできます.

    関連接続

  • 以太坊開発者リソースツールセット
  • Remix
  • Solidity言語
  • React菜鳥教程
  • 以太坊DApp開発環境配置