JavaScript
Node.js
Ethereum
solidity
truffle

Truffleを使ってEthereumでペットショップアプリを作る〜後半:アプリケーション〜

これまで

前半ではコントラクト部分を作ってきましたが
後半はWebUIの部分を作っていきます。
JavaScriptを久々に見たので心が穏やかになりました。

アプリケーション

srcの中にあれこれ格納されており、index.htmlが骨格部分、jsの中にあるapp.jsが動かす部分です。
bootstrapとweb3が最初から入っています。

web3.jsとは
Ethereumノードとやり取りできるJavaScriptライブラリだそうです

app.jsが親切にも穴埋め式にしてくれていますので、以下はReplace me...となっている箇所に入れていきます。

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

app.js
    initWeb3: function() {
    // すでに有効可されていたらそれをそのまま使う
    if (typeof web3 !== 'undefined'){
      App.web3Provider = web3.currentProvider;
    }else{
      App.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545');
    }
    web3 = new Web3(App.web3Provider);

    return App.initContract();
  },

  initContract: function() {
    $.getJSON('Adoption.json',function(data){
      var AdoptionArtifact = data;
      App.contracts.Adoption = TruffContract(AdoptionArtifact);

      App.contracts.Adoption.setProvider(App.web3Provider);
      // 状態を呼び起こす
      return App.markAdopted();
    });

    return App.bindEvents();
  },

状況の取得と表示

チェーンの中にデプロイされているコントラクトの状態を取得し、
販売中だったらそのままAdoptボタンを表示し、
すでに引き取られていたらボタンを押せないようにする必要があります。

'app.jsの真ん中少し後ろにあるmarkAdopted:`の箇所に記述します。

app.js
markAdopted: function(adopters, account) {
    /*
    デプロイしたAdoptionより、getAdoptersをcallする。
    */
    var adoptionInstance;
    App.contracts.Adoption.deployed().then(function(instance){
      adoptionInstance = instance;
      return adoptionInstance.getAdopters.call();
    }).then(function(adopters){
      /*
      adoptersを順番に取り出し、「0じゃない」=すでに引き取られているものがあれば、
      パネルのボタンの文字をSuccessにし、非表示とする
      */
      for(i=0; i<adopters.length; i++){
        if(adopters[i] !== "0x0000000000000000000000000000000000000000"){
          $(".panel-pet").eq(i).find("button").text("Success").attr('disabled', true);
        }
      }
    }).catch(function(err){
      console.log(err.message);
    });
  },

引き取った際の処理

Adoptすると、
該当のpetIdに自分のaccountを紐付けてadopterになり、状況を更新して再表示する必要があります。
今度はhandleAdoptのところに記述していきます。

app.js
  handleAdopt: function(event) {
    event.preventDefault();

    // 選択したidをpetIdにする
    var petId = parseInt($(event.target).data('id'));
    var adoptionInstance;

    // アカウントを取得
    web3.eth.getAccounts(function(error, accounts){
      if(error){
        console.log(error);
      }
      var account = accounts[0];

      App.contracts.Adoption.deployed().then(function(instance){
        adoptionInstance = instance;

        // 現在のアカウントでコンストラクトを実行
        return adoptionInstance.adopt(prtId,{from:account});
    }).then(function(result){

      // markAdoptedを行って表示を更新する
      return App.markAdopted();
    }).catch(function(err){
      console.log(err.message);
    });
  });
};

確認用のウォレットを導入

Etherの動きを確認するためにプライベートネットに接続できるウォレットを設定します。
チュートリアルではMetaMaskを使用していたので今回もそれでいきます。

Import Existing DENより、Ganacheに表示されているMNEMONICを入力します。
Custom RPCを選択し、Ganacheで立ち上げているRPCサーバーのアドレスであるhttp://127.0.0.1:7545を入力

うまくいくと。index0である一番上のアカウントの残高が載るかとおもいます

ローカルサーバーの立ち上げ

できたアプリケーションを確認するためにサーバーを立ち上げてブラウザから確認します。
チュートリアルのやつはご丁寧にも直下にあるbs-config.jsonpackage.jsonというやつを準備してくれて、lite-serverを立ち上げるだけになっています。

$ npm run dev

上手く行けばペットショップが立ち上がるかと思います。
Adoptのボタンを押すとgasとgas limitを設定するところがでてきますので数字を入れ、好きな子を選んで引き取ってあげてください

あとがき

おもったよりスイスイできました。
手数料しかかからなかったのでペットショップというより里親募集サイトみたいなものでしょうか。

ソース全体はこちら
https://github.com/gagaga81/pet-shop