• トップ
  • ブログ一覧
  • 【後編】Ethereum Pet Shop DAppの作成とテスト~UI 作成編~
  • 【後編】Ethereum Pet Shop DAppの作成とテスト~UI 作成編~

    広告メディア事業部広告メディア事業部
    2020.07.29

    IT技術

    後編~Ethereum Pet ShopでDApp作成とテスト~

    前回に引き続き「Ethereum Pet Shopを使って DAppの作成からテスト」まで行ってみたいと思います!

    中編では、実際にコントラクトを作成し、テストまで行っていきました。

    今回は、UI の作成を行っていきたいと思います!

    制作工程

    1. 環境設定
    2. Truffle Box を使って Truffle プロジェクトを作成
    3. コントラクト作成
    4. コントラクトをコンパイルしてデプロイ
    5. コントラクトのテスト
    6. UI 作成
    7. ブラウザ上の DApp でログインする

    UI の作成

    pet shop の Truffle Box には、アプリのフロントエンドファイルが src ディレクトリに内包されています。

    仕様は以下の通りです。

    1. Lite Server を起動
    2. 購入画面で選んだペットの「Adopt」ボタンをクリック
    3. MetaMask に登録した Ethereum アドレスで承認

    このコントラクトから、MetaMask 経由で対話できる UI が「web3」です。

    web3 のインスタンス化

    アプリはグローバルオブジェクトで、int( ) 内にペットのデータがロードされ、intWeb3( )関数で読み込みます。

    また、Ethereum Blockchainとの対話に必要なデータがパッケージ化されている「Web3JavascriptLibrary」も使えます。

    これにより、「ユーザーアカウントの取得」「トランザクションの送金」「コントラクトとの対話」などが出来ます。

    【Web3JavascriptLibrary】
    https://github.com/ethereum/web3.js/

    app.js ファイルを修正

    まず、src/js/app.js ファイルをテキストエディタで開きます。

    app.js ファイルを、以下のコードに修正します。

    1App = {
    2  web3Provider: null,
    3  contracts: {},
    4
    5  init: async function() {
    6    // ペットの情報をロードします。
    7    $.getJSON('../pets.json', function(data) {
    8      var petsRow = $('#petsRow');
    9      var petTemplate = $('#petTemplate');
    10
    11      for (i = 0; i < data.length; i ++) {
    12        petTemplate.find('.panel-title').text(data[i].name);
    13        petTemplate.find('img').attr('src', data[i].picture);
    14        petTemplate.find('.pet-breed').text(data[i].breed);
    15        petTemplate.find('.pet-age').text(data[i].age);
    16        petTemplate.find('.pet-location').text(data[i].location);
    17        petTemplate.find('.btn-adopt').attr('data-id', data[i].id);
    18
    19        petsRow.append(petTemplate.html());
    20      }
    21    });
    22
    23    return await App.initWeb3();
    24  },
    25
    26  initWeb3: async function() {
    27    // DAppを使用できるブラウザーか確認する
    28if (window.ethereum) {
    29  App.web3Provider = window.ethereum;
    30  try {
    31    // アカウントへのアクセス要求
    32    await window.ethereum.enable();
    33  } catch (error) {
    34    // ユーザーがアカウントのアクセスを拒否しました
    35    console.error("User denied account access")
    36  }
    37}
    38// Web3プロバイダーのウィンドウを開く
    39else if (window.web3) {
    40  App.web3Provider = window.web3.currentProvider;
    41}
    42// もし挿入されたWeb3インスタンスが検出されない場合は、Ganacheに戻します
    43else {
    44  App.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545');
    45}
    46web3 = new Web3(App.web3Provider);
    47
    48    return App.initContract();
    49  },
    50
    51<span style="color: rgb(255, 0, 0);" data-mce-style="color: #ff0000;">  initContract: function() {
    52    $.getJSON('Adoption.json', function(data) {
    53  //必要なContract Artifactファイルを取得し、@truffle/contractでインスタンス化します
    54  var AdoptionArtifact = data;
    55  App.contracts.Adoption = TruffleContract(AdoptionArtifact);
    56
    57  // コントラクトの為にプロバーダーを設定します
    58  App.contracts.Adoption.setProvider(App.web3Provider);
    59
    60  // データ取得と受け取ったペットをマーキングする為にコントラクトを使用します
    61  return App.markAdopted();
    62});
    63</span>
    64
    65    return App.bindEvents();
    66  },
    67
    68  bindEvents: function() {
    69    $(document).on('click', '.btn-adopt', App.handleAdopt);
    70  },
    71
    72  markAdopted: function(adopters, account) {
    73  var adoptionInstance;
    74
    75App.contracts.Adoption.deployed().then(function(instance) {
    76  adoptionInstance = instance;
    77
    78  return adoptionInstance.getAdopters.call();
    79}).then(function(adopters) {
    80  for (i = 0; i < adopters.length; i++) {
    81    if (adopters[i] !== '0x0000000000000000000000000000000000000000') {
    82      $('.panel-pet').eq(i).find('button').text('Success').attr('disabled', true);
    83    }
    84  }
    85}).catch(function(err) {
    86  console.log(err.message);
    87});
    88
    89  },
    90
    91  handleAdopt: function(event) {
    92    event.preventDefault();
    93
    94    var petId = parseInt($(event.target).data('id'));
    95
    96    var adoptionInstance;
    97
    98web3.eth.getAccounts(function(error, accounts) {
    99  if (error) {
    100    console.log(error);
    101  }
    102
    103  var account = accounts[0];
    104
    105  App.contracts.Adoption.deployed().then(function(instance) {
    106    adoptionInstance = instance;
    107
    108    // アカウントを送信してデータ取得としてのトランザクションを実行します
    109    return adoptionInstance.adopt(petId, {from: account});
    110  }).then(function(result) {
    111    return App.markAdopted();
    112  }).catch(function(err) {
    113    console.log(err.message);
    114  });
    115});
    116
    117  }
    118
    119};
    120
    121$(function() {
    122  $(window).load(function() {
    123    App.init();
    124  });
    125});

    コントラクトのインスタンス化

    上記コードの Artifact は、展開されたアドレスや ABI などのコントラクトに関する情報です。

    ABI「変数」「関数」「そのパラメーターを含むコントラクトとの対話方法」を定義するJavaScriptオブジェクト
    TruffleContract( )関数TruffleContract( )関数を通過すると、対話可能なコントラクトのインスタンスが作成されます
    App.web3Provider変数web3 に最初に設定する時に格納した値が入ります
    markAdpted( )関数既に受け入れが決まったペットを読み込みます

    確認

    UI のアップデート

    Adoption.sol コントラクトをデプロイすると、「getAdopters( )関数」を呼び込みます。

    「adoptionInstance 変数」でデータを呼び出し、コントラクト外で宣言した後、インスタンスにアクセスできるようにします。

    loop でデータを検索し、Ethereum アドレスが格納されている petId を見つけ出すと「Success」ボタンに変わります。

    確認

    adopt()関数の処理

    ペットの ID」と「アカウントに格納したアドレスを含むオブジェクト」を使用して、adopt( )関数を実行することにより、トランザクションを送信します。

    エラーがない場合は、「markAdopted( )関数」を呼び出して、UI を新しく保存されたデータと同期します。

    MetaMask の設定

    ブラウザアプリをインストール

    まず、MetaMask のブラウザアプリをインストールします。

    ログインする

    インストール後に、デプロイでターミナル上に表示された Mnemonic を使用し、ログインします。

    ネットワークから「カスタムRPC」を選択し、「http://127.0.0.1:7545」を入力しましょう。

    すると、各アカウントにテスト用の「100ETH」が表示されます。

    ただし、コントラクトのデプロイ時や Ganache でテストに使った場合は、「Gas」 が差し引かれている場合があります。

    「コントラクト」「Ganache」「MetaMask」が連携されたことを確認してください。

    Lite-Server のインストールと構成

    まず、Lite-Server をインストールします。

    1   //lite-serverの起動
    2    $ npm install -g lite-server
    3    //*****プロジェクトルート 
    4    $ pet-shop-tutorial pet-shop > lite-server
    5    //******プロジェクトルート

    ベースディレクトリーの設定

    「bs-config.json」をテキストエディタで開きます。

    以下のコマンドの場合、 Webサイトファイル用の「./srcディレクトリー」と、contract artifacts用の「./build/contractsディレクトリー」を追加します。

    1{ "server": { "baseDir": ["./src", "./build/contracts"] } }

    dev コマンドを追加

    プロジェクトのルートディレクトリーに、「package.json」ファイルがあります。

    このファイルに、「dev コマンド」を追加します。

    スクリプトオブジェクトを使用すると、コンソールコマンドを単一の npm コマンドに変換できます。

    1"scripts": {
    2  "dev": "lite-server",
    3  "test": "echo \"Error: no test specified\" && exit 1"
    4},

    実行

    Lite-Server を実行しましょう。

    以下のコマンドで、MetaMask が起動します。

    1npm run dev

    必ず、Web3 で設定したコンパイル設定のポート上「http://127.0.0.1:7545」でログインしてください。

    app.js ファイルで設定したアカウントで開くと、認証後に「Adopt」ボタンが「Success」に変更されます。

    さいごに

    「Ethereum Pet Shop」は、Ethereum ブロックチェーンのトレーニング用プロジェクトです。

    コントラクトの作成」から「デプロイの仕方」「MetaMask への連携」「Ganache でのテスト」まで制作手順が分かります。

    このプロジェクトを通して、プライベートブロックチェーン「Ethereum」の可能性を感じました。

    「Ethereum」は、決済手段だけではなく、認証手段として使用することで DApp の活用方法も広がります

    新たな Web3 の世界がインターネットに変革を起こしそうですね!

    おすすめの本

    マスタリング・イーサリアム ―スマートコントラクトとDAppの構築
    マスタリング・イーサリアム ―スマートコントラクトとDAppの構築

     

    こちらの記事もオススメ!

    featureImg2020.08.14ブロックチェーン特集知識編ブロックチェーンとコンセンサスアルゴリズム実装編【Blockchain Data Managerを使ってみたEt...

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...

    関連記事

    featureImg2020.07.24【前編】Ethereum Pet ShopでDAppを作成してみた!~環境構築編~~前編~Ethereum Pet ShopでDApp作成とテスト今回は、「Ethereum Pet Shopを使って ...

    featureImg2020.07.28【中編】Ethereum Pet Shop DAppの作成とテスト~コントラクト作成編~~中編~Ethereum Pet ShopでDApp作成とテスト今回は、前回に引き続き、「Ethereum Pet S...

    featureImg2020.07.29【後編】Ethereum Pet Shop DAppの作成とテスト~UI 作成編~後編~Ethereum Pet ShopでDApp作成とテスト~前回に引き続き「Ethereum Pet Shopを使...

    広告メディア事業部

    広告メディア事業部

    おすすめ記事