webページにEtherの残高を表示してみる（その２）

# トークンの保有数を追加する
前回の「[webページにEtherの残高を表示してみる](https://qiita.com/minato774/items/946b882e4fdeb062cbbf)」に続き、これに独自のトークンの保有数を表示をしたい。
ICOとかのサイトに設置してチェックできる機能というのは、便利なのではないだろうか

# JSON-RPCでコントラクトを実行する
トークンの保有数を取得するにはトークンのコントラクトの```balanceOf(address)```のメソッドを実行させる必要がある。
JSON-RPCを使ってコントラクトのFunctionを呼び出すには、```eth_call```でコントラクトのメソッドシグネチャとエンコードされたパラメータを送信する。
そのメソッドシグネチャについてはコントラクトのFunctionをSHA3でHASH化してその最初の4byteを使う・・・とのこと
詳しくは[Ethereum-Contract ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI)を参照。

Geth Consoleから`web3.sha3()`で、使いたいFunctionをHASH化、その先頭4byteを取得する。

```geth.console
> web3.sha3('balanceOf(address)').substring(0,10)
"0x70a08231"
```

取得した結果を32byteデータにする
（残りの桁を0で埋める)

```
0x70a08231000000000000000000000000
```

トークンの保有数を表示させたいアドレスをメソッドシグネチャに連結する
(アドレスはデタラメの適当です)

```
0x70a082310000000000000000000000009876543210FedcBa9876543210FedcBa98765432
```

出来た結果を`eth_call`の`data`パラメータとして送信するのでjson部分を作成する

```json.
{
  "jsonrpc":"2.0",
  "method":"eth_call",
  "params":
  {
    "to":"0x9876543210ffddeea00987654ffdedeEdEdFdFd012",
    "data":"0x70a082310000000000000000000000009876543210FedcBa9876543210FedcBa98765432",
    "latest",
  }
  "id":65534
}
```

出来たJSONをropstenに送る形に整え送信。
JSONが正常であればresponsのように返ってくる。

```request.
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x987654321...(contract_address)...","data":"0x70a082310000000000000000000000009876543210FedcBa9876543210FedcBa98765432"},"latest"],"id":65534}' https://ropsten.infura.io/
```

```respons.
{"jsonrpc":"2.0","id":65534,"result":"0x00000000000000000000000000000000000000000000000000000000000e57e0"}
```

コンソールからcurlを使って正しくレスポンスを取得できるようであれば、あとは簡単です。


# PHPにトークン保有数の取得を追加する

前回に作ったweb3balance.phpの`main`Function部分を書き換えてトークンの保有数の取得を追加する

```web3balance.php

function main($address) {
    // check
    $address = trim($address);
    if(!$address) return false;
    if(!preg_match('/0x[0-9a-f]+/i',$address)) {
        return false;
    }
    // getBalance
    $data = [
        "jsonrpc" => "2.0",
        "method" => "eth_getBalance",
        "params" => [$address,"latest"],
        "id" => 65756,
    ];
    //
    $response = postJson($data);

    $getBalance = json_decode($response);

    $ethbalance = decodeHex($getBalance->result);

    $cHash = "0x70a08231";

    $contractHash = str_pad($cHash,34,"0").substr($address,2);

    $contract_address = "0x987654321...(ContractAddress)";

    $data = [
        "jsonrpc" => "2.0",
        "method" => "eth_call",
        "params" => [[ "to" => $contract_address, "data" => $contractHash ],"latest"],
        "id" => 65757,
    ];

    $response = postJson($data);

    $balanceOf = json_decode($response);

    $tokenbalance = decodeHex($balanceOf->result) * pow(10,16);

    $jsonData = [
        "address" => $address,
        "ethBalance" => $ethbalance,
        "tokenBalance" => $tokenbalance,
        "status" => "success"
    ];
    return $jsonData;
}

```

PHPのトークン保有数取得の追加にあわせて、HTML表示部分にも表示枠とレスポンスの取得・入力を追加する

```web3balance.html

<form id="myForm">
    ETHアドレス<br/>
    <input type="text" id="address" name="address" size="64" value="Ethereum Address"><br />
    ETH残高<br/>
    <input type="text" id="ethbalance" name="ethbalance" size="64"><br />
    TOKEN残高<br/>
    <input type="text" id="tokenbalance" name="tokenbalance" size="64"><br />
    <input type="button" id="btnCheck" value="check">
</form>
<script type="text/javascript">
    $(function(){
        $("#ethbalance").html("Response Values");
        $("#btnCheck").click( function() {
            var jsondata = {
                address: $("#address").val()
            };
            console.log(JSON.stringify(jsondata));
            $.ajax({
                type : 'post',
                url : 'web3balance.php',
                data : JSON.stringify(jsondata),
                contentType : 'application/JSON',
                dataType : 'JSON',
                scriptCharset : 'utf-8',
                success : function(data) {
                    console.log(JSON.stringify(data));
                    if(data.status=="success") {
                        console.log("success");
                        $("#ethbalance").val(data.ethBalance);
                        $("#tokenbalance").val(data.tokenBalance);
                    }
                    else{
                        console.log("failer");
                    }
                },
                error : function(data) {
                    console.log("error");
                    console.log(JSON.stringify(data));
                }
            });
        });
    });
</script>

```

上記のコードは前に作ったものに修正を加えた感じにしております。
私の場合はコントラクトはRopstenにデプロイして置いたminaTokenをコントラクトとして使用しました。
またトークンのDecimalsが2に設定されているので、10進に変換するところは若干異なります。

これでアドレスを入力してCheck!とすると、Etherの残高と、トークンの保有数が表示されます。

最初に調べた際には結構簡単に見えたものですが、メソッドシグネチャを作成するなど部分で詰まったりしました。
この次は、Gasを消費する`eth_sendTransaction`を行いたいと思います。


# 参考
以下の記事を参考にさせて頂きました。ありがとうございます。
https://github.com/ethereum/wiki/wiki/JSON-RPC
https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI

[JSON-RPC経由でEthereumのContractを作る](https://qiita.com/kanehara/items/5f09401813b52a326ac5)
[EthereumノードにJSON-RPC API経由でアクセスする](https://qiita.com/kanehara/items/5f09401813b52a326ac5)