LoginSignup
2

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-04-24

webページで簡単にEtherやTokenの残高が表示できるようにしてほしい。
という話からまた色々探してみる。

Geth JSON-RPCを使う

最初に考えたのがGethを使って繋ぎこむ方法。
とはいえ今まで得意とする分野のphpを使っての繋ぎこみは難しく、調べていくうちにたどり着いたのがJSON-RPC。

PHP → GETH(JSON-RPCサーバ)→ Ethereumノード

この形でEthereumから残高を取得できると考えました。
私が得意とするPHPの場合、curlを使えばJSON-RPCを簡単に送れるというのもありましたので、PHPでJSON形式をPOSTする方法を参考に致しました。
接続先は、Gethを--rpcの起動オプションをつけてRPCを有効な状態にして起動させている自身のLocalhostを指定しています。

web3balance.php

function postJson($json){
    //
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://127.0.0.1:7545');
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($json));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

    // getBalance
    $data = [
        "jsonrpc" => "2.0",
        "method" => "eth_getBalance",
        "params" => [$address,"latest"],
        "id" => 65756,
    ];
    //
    $response = postJson($data);

ここで問題が発生。
自身の開発環境のPC上で組んだ後、サーバ上で動作させようとして、そこでgethのインストールが上手くいかないという事態が発生しました。
またGethがインストール出来たとしてもノードの同期も行う必要があり、その分容量を使ってしまう。
インストールが対処出来ても容量問題が厄介です。
何かGethを上手くインストールする方法はないものか、同期させる必要はどうするか?

INFURAのJSON-RPC APIを使ってみる

他の方のWeb WalletやスマホWalletがどうしているのか調べてみたら解決は早かったです。
「INFURAがJSON-RPCに対応している」
ということがわかれば十分でした。
INFURAを使えば同期させる必要もGethをインストールする必要も無くなります。
ただし、問題はINFURAのサービスに乗っかった状態のままでも良いのか、ということです。
いずれはJSON-RPCのサーバを立ててノードに繋いでおく必要があるとは考えます。

今は利用してでも表示させることを優先しました

web3balance.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>web3.getBalance</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
</head>
<body>
<h1>web3.getBalance</h1>
<form id="myForm">
    ETHアドレス<br/>
    <input type="text" id="address" name="address" size="64" value="Ether address"><br />
    ETH残高<br/>
    <input type="text" id="ethbalance" name="ethbalance" 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);
                    }
                    else{
                        console.log("failer");
                    }
                },
                error : function(data) {
                    console.log("error");
                    console.log(JSON.stringify(data));
                }
            });
        });
    });
</script>
</body>
</html>

HTMLと同じ階層にJSON-RPCを送信するPHPも設置します。

web3balance.php

<?php
//
function postJson($json){
    //
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://ropsten.infura.io/');
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($json));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}
//
function decodeHex($hex){
    $dec = null;
    if(substr($hex, 0, 2)=='0x') {
        $hex = substr($hex, 2);
    }
    if(preg_match('/[0-9a-f]+/', $hex)) {
        $dec = hexdec($hex) / pow(10, 18);
    }
    return $dec;
}
//
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);
    $jsonData = [
        "address" => $address,
        "ethBalance" => $ethbalance,
        "status" => "success"
    ];
    return $jsonData;
}
//
$result = false;
$jsonString = file_get_contents('php://input');
$jsonData = json_decode($jsonString);
if(isset($jsonData->address)) {
    $address = $jsonData->address;
    //
    $result = main($address);
}
if($result) {
    $json = $result;
}else{
    $json = [
        "address" => $address,
        "status" => "error",
    ];
}
//
header('Content-Type: application/json');
echo json_encode($json);

このコードはテストのこともあるのでRopstenのTestnetに接続を行いEther残高を返してもらうことにしています。Liveの場合は、CURLOPT_URLのアドレスをInfuraのLiveに変更するだけです。

curlでJSONを送る場合、Content-Type: application/jsonの指定がないとエラーが表示されてダメな様子。
以前はなくても行けたようですが厳格になったのだと思います。

    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));

JSONで送る内容は残高を取得するeth_getBalanceのメソッド。
こちらの配列をjson_encodeしてから送信しています。

    // getBalance
    $data = [
        "jsonrpc" => "2.0",
        "method" => "eth_getBalance",
        "params" => [$address,"latest"],
        "id" => 65756,
    ];

パラメータの内容についてはまだ勉強中です。

ブラウザからweb3balance.htmにアクセスしてEtherアドレスを入力してcheckボタンを押す。
ローカルのweb3balance.phpへEtherのアドレスが送信されて、それを受け取った後、InfuraのRopsten JSON-RPCへメソッドとパラメータをPOST。
Infuraから正常にレスポンスを取得して、Etherの残高をJson形式に整形してHTMLへレスポンスとして戻す。
それを受け取ってからETH残高の欄に表示させる。

こうのようなことでWebページにEtherの残高を表示することが出来ます。
結構色々な方々がJSON-RPCのことを書かれていますので参考になると思います。

web3balance201804241650.png

次は、これにコントラクトした独自トークンの残高を表示させます。

参考

以下のサイトを参考にさせて頂きました。ありがとうございます。
https://github.com/ethereum/wiki/wiki/JSON-RPC
https://infura.io/
https://infura.io/docs

JSON-RPC API で geth を便利に使う
Ethereum(Geth)でJSON RPCを使って外部からアクセスする

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2