pet-shop tutorialをやってみた

##初めに
Dappsを作ってみたいと思っていて、ネットでチュートリアルのようなものを探していたらTRUFFLE SUITEというサイトにたどり着きました。そこで簡単そうなETHEREUM PET SHOPというチュートリアルがあったので、試してみました。チュートリアルは英語で書かれているので、少し時間がかかりました。そこまで、難しい英語ではないのですらすら進めていける人も多いと思いますが、自分みたいに時間がかかる人もいると思うので、簡単に和訳？要約？したものを載せておきます。メモ程度に使ってください。

ETHEREUM PET SHOP : https://www.trufflesuite.com/tutorials/pet-shop


##対象
HTMLとJavascriptの知識がある人でdappsが初めての人向け

## 概要
ペットの販売を行うアプリ
dappでEthereum addressとペットをうまく関連づけたい
pet shopにはペット１６匹分のスペースがあり、ペット用のデータベースはすでにある

サイトの構造とスタイリングは提供される。
スマートコントラクトとフロントエンド側のロジックを用意すればよい

## 目次

1. 開発環境のセッティング
2. TruffleBoxを使ったTruffle project作成
3. スマートコントラクトのコーディング
4. スマートコントラクトのコンパイルとマイグレイティング
5. スマートコントラクトのテスト(今回はここまで)
6. スマートコントラクトとやり取りするUI作成
7. ブラウザでdappを使う

## 開発環境のセッティング

###準備
- nodejsとnpmのインストール
- gitのインストール

### truffleのインストール
終ったらnpm install を使ってインストール
`npm install -g truffle`
`truffle version`でバージョンが確認できればインストールできてる

### Ganache
Ganache : http://truffleframework.com/ganache
personal blockchainを視覚的に見ることができる

- コントラクトのデプロイ
- アプリケーション開発
- テスト
などができる

##TruffleBoxを使ったTruffle project作成
適当なディレクトリを作ってそこへ移動

今回はpet-shopという特別なTruffle Boxを作成する
基本的なプロジェクトの構造やUI用のコードなどが入っている
`truffle unbox pet-shop`

デフォルトのTruffleには次のようなファイルやディレクトリがある

- Contracts ... スマートコントラクト用のsolidityファイルやMigrations.sol(後で説明)がある
- migrations ... Truffleはマイグレーションを使って管理するため、ここにmigrationファイルがある 
- test ... Javascriptやsolidityで書かれたtest用のスクリプトがある
- truffle-config.js ... TruffleのConfiuratio ファイル
ほかのものは今回はあまり使わない

##スマートコントラクトのコーディング
contractsディレクトリ直下にAdaption.solを作成
コード自体はJavaScriptと似ている

```Adoption.sol
pragma solidity ^0.4.24;		// 1

// 2
contract Adoption{
	// 3
	address[16] public adopters;

	// 4
	function adopt(uint petId) public returns (uint) {
		require(petId >= 0 && petId <= 15);

		adopters[petId] = msg.sender;

		return petId;
	}

	// 5
	function getAdopters() public view returns (address[16] memory){
		return adopters;
	}
}
```

### 1. コンパイラのバージョン指定

すべてのファイルに記述する必要がある
^0.5.0は0.5.0以上0.6.0未満のコンパイラを使うことを表している

### 2.変数の宣言

Solidityは静的型付け言語であり、型を指定する必要がある
Solidityにはaddress型というものがあり、Ethereumアドレスを20byteの値として保存できる
Ethereumのスマートコントラクトやアカウントはアドレスを持っておりそのアドレスを使ってEtherを送りあったりする

ペットの飼い主のアドレスを格納する
配列は固定長と可変長のどちらも宣言できるが、ここでは固定長で宣言している

publicで宣言された変数はgetterメソッドが自動生成される
配列の場合は各要素に対するgetterが用意されているだけのため、配列を渡したい場合には新しいgetterメソッドを用意する必要がある(->5) 
　　　
###3.ペット購入(引き受け)用関数

Solidityの関数は引数と戻り値の引数を指定する必要がある
ペットの数は16匹(Backgroundより) なので、引数の値がその条件を満たしているかrequireメソッドで確認している　

msg.senderはこの関数を呼び出した人やスマートコントラクトのアドレスであり、そのアドレスをadoptersに代入している
確認用のため返り値としてpetIdを返している

###4.配列のgetterメソッドの作成

上記の通り自動生成されるgetterは配列の要素しか返さない。これから作るUIではすべての飼い主の状態を知りたいため、配列を返すgetterを用意する

memoryは一時的にデータを保持するもの(storageはブロックチェーンに永久保存する)
viewはコントラクトの状態を変えない関数のことを表しており、データを参照するだけの関数ではviewキーワードが用いられる

##スマートコントラクトのコンパイルとマイクレーティング

Solidityはコンパイラ言語のためコンパイルをする必要がある
EVMと呼ばれるEthereum Virtual Machineで実行できるコードにする　
###Compilation
pet-shop-tutorialディレクトリ直下で以下のコマンドを打つ
`truffle compile`

Windowsの人でエラーが出た人は以下のサイトを参照してください
https://www.trufflesuite.com/docs/advanced/configuration#resolving-naming-conflicts-on-windows
　
###Migration
マイグレーションとはアプリケーションのコントラクトの状態を変化させること
マイグレーションの設定はMigration.solに書いてある

一つ目のマイグレーションファイルは既にあるのでmigrationsディレクトリ直下に2_deploy_contracts.jsファイルを作成

``` 2_deploy_contracts.js
var Adoption = artifacts.require("Adoption");

module.exports = function(deployer){
	deployer.deploy(Adoption);
};
```

マイグレーションを行う前にデプロイするためのブロックチェーンが必要
Ganacheを使うことでパーソナルブロックチェーンを用意できるので、起動しておく

`truffle migrate`でマイグレーションを実行

Ganacheでブロックチェーンの変化が見れます

100Etherから少しEtherが減っている
これはマイグレーションにコストがかかったため

TX COUNTが4のものが現在のブロックを表しています(0は前のブロック)

##　スマートコントラクトのテスト    
TruffleではテストをSolidityとJavaScriptの両方で書けます
今回はSolidityでtestディレクトリ直下にTestAdoption.solファイルを作成

``` TestAdoption.sol
pragma solidity ^0.4.24;

// 1
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Adoption.sol";

contract TestAdoption{
	// 2
	Adoption adoption = Adoption(DeployedAddresses.Adoption());

	uint expectedPetId = 8;

	address expectedAdopter = address(this);


	// 3
	function testUserCanAdoptPet() public {
		uint returnId = adoption.adopt(expectedPetId);

		Assert.equal(returnId, expectedPetId, "Adoption of the expected pet should match what is returned.");
	}

	// 4
	function testGetAdopterAddressByPetId() public {
		address adopter = adoption.adopters(expectedPetId);

		Assert.equal(adopter, expectedAdopter, "Owner of the expected pet should be this contract");
	}

	// 5
	function testGetAdopterAddressByPetIdArray() public {
		address[16] memory adopters = adoption.getAdopters();

		Assert.equal(adopters[expectedPetId], expectedAdopter, "Owner of the expected pet should be this contract");
	}
}
```

### 1. 必要なファイルのインポート
- Assert.sol ... テストで使うAssertion(等しい、等しくない、空）が使えるようになる。
- DeployedAddress.sol ... テストを行うときTruffleは新しいインスタンスをブロックチェーンにデプロイする。そのコントラクトのアドレス使える
- Adoption.sol ... テスト用ファイル

### 2. 変数の用意

- adoption ... テスト用のスマートコントラクト
- expectedId ... テストに使うID
- expectedAdopter ... このコントラクトのアドレス

### 3. adopt関数のテスト
adopt関数のテストを行う
引数にexpectedIdを渡したときに戻り値がexpectedIdと等しいかテストしている

### 4. getterメソッドのテスト
publicで宣言した変数は自動的にgetterメソッドを持つ
それが正しく機能しているかテストする

5-3でAdoptionスマートコントラクトのadopt関数を呼んだ。
adopters配列のkey(8)に対応するvalueはこのコントラクトのアドレスである。
それをテストしている

### 5. 配列のgetterのテスト
Adaption.solではadopters配列をまとめて返す関数を用意した
それをテストする
配列を受け取りその配列のkey(expectedId)がexpectedAdopterであるかをチェックします。
            
testのコマンドは`truffle test`
3つのテストがpassしていれば成功

## 最後に
次は残りのUIのほうに挑戦してみます。