gethの機能やコントラクトをweb3.jsを利用して呼び出す


jsプログラムやWeb経由で利用した場合の方法。

## 前提

[こちら](http://qiita.com/zaburo/private/9c8fab5da3b7d782ee89)の記事を参考にgethやコントラクトが展開されている状態を想定しています。

## web3.jsのインストール

作業ディレクトリを作ってweb3をインストールします。

```bash
mkdir web3
cd web3
npm install web3@0.20.0
```

>2017年8月12日時点の最新はbeta 1.0.0-18でしたが、うまく動かないので古いバージョンを利用。

## コンソールアプリからの利用

まずはjsコンソールアプリからの利用を確認してみます。バッチなどで利用する場合はやはりコンソールアプリが便利です。

### gethコマンドの利用

まずはcoinbaseを取得・表示してみます。

```js:test.js
var Web3 = require('web3');
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8575'));

var coinbase = web3.eth.coinbase;
var balance = web3.eth.getBalance(coinbase);
console.log("balance:", balance);
```

>アドレスは環境に応じて変えて下さい。

実行してみます。

```bash
node test.js

balance: { [String: '1.03302002804264e+23'] s: 1, e: 23, c: [ 1033020028, 4264000000000 ] }
```

### コントラクトの利用

次に展開済のコントラクトを呼び出してみます。

```js:test.js
var Web3 = require('web3');
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8575'));

//コントラクトのアドレス
var address = "0x56bad31cb803f82bebe32d080314d11ddcef0ea9";

//abi情報
var abi = [{"constant":true,"inputs":[],"name":"Hello","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"}];

//コントラクトの取得
var contract = web3.eth.contract(abi).at(address);

//実行
var response = contract.Hello.call();

console.log("response:",response);
```

実行してみます。

```bash
node test.js

response: Hello World
```

Hello Worldが返りました。

## Webからの利用

Webから利用してみます。コンソール時とほぼ同様に扱うことができます。
なお、Webからの利用にはweb3.min.jsを利用しますが、これはnpmでインストールした場合、/node_modules/web3/dist/以下に存在しますので、コピーして利用します（ここではそのまま利用しています）。

>CDNも[こちら](https://cdn.rawgit.com/ethereum/web3.js/develop/dist/web3.js)にあるようです。。

まずはgethコマンドから。

```html
<!doctype html>
<html>
<body>
    <button id="btn">exec</button>
    <!-- 読み込み -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
     <script src="node_modules/web3/dist/web3.min.js"></script> 
    <script>
        $(function(){
            $("#btn").click(function(){
                var web3 = new Web3();
                web3.setProvider(new web3.providers.HttpProvider('http://localhost:8575'));

                var coinbase = web3.eth.coinbase;
                var balance = web3.eth.getBalance(coinbase);
                alert(balance);
            });
        });
    </script>
</body>
</html>
```

jQueryとの共存も問題ないようです。
次に、コントラクトの実行。

```html
<!doctype html>
<html>
<body>
    <button id="btn">exec</button>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
     <script src="node_modules/web3/dist/web3.min.js"></script> 
    <script>
        $(function(){
            $("#btn").click(function(){
                var web3 = new Web3();
                web3.setProvider(new web3.providers.HttpProvider('http://localhost:8575'));

                var address = "0x56bad31cb803f82bebe32d080314d11ddcef0ea9";

                var abi = [{"constant":true,"inputs":[],"name":"Hello","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"}];

                var contract = web3.eth.contract(abi).at(address);

                var response = contract.Hello.call();

                alert(response);
            });
        });
    </script>
</body>
</html>
```

どちらも問題ないようです。

## その他

実際にサービスを開発する場合は、アカウントの追加やコントラクトのデプロイ自体をweb3.js経由で行うこともできます。
それらの方法は随時追加したいと思います。

### Eventの監視

サンプルとしては（ABIが）冗長ですが、EditPoint()というイベントが設定されている場合の監視。
アドレスとABIからコントラクトを作成し、その中のEventを指定して監視するようです。

>下記スクリプトを実行すると待ち状態になり、Event発生時にEdit event detected!ログが出力されます。

#### 監視コードの追加

HelloWorldにEvent機能を追加します。

```solidity
pragma solidity ^0.4.13;

contract HelloWorld{
    
    //イベント定義
    event ExecHello(address from, string operation);
    
    //メソッド
    function Hello() constant returns (string){
        //イベントイベント実行
        ExecHello(msg.sender, "Exec Hello!");
        
        //return
        return "Hello World";
    }
}
```

>ポイントは戻り値をconstantにしないことです。constantはEventを発火しないようです。

#### 監視コード

下記スクリプトをコンソールで実行すると待ち状態となります。

```js
var Web3 = require('web3');
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8575'));

//コントラクトのアドレス
var address = "0x1a890d0b9d7355ae641d40db8425c888de3a0ef0";

//ABI
var abi = [{"constant":false,"inputs":[],"name":"Hello","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"from","type":"address"},{"indexed":false,"name":"operation","type":"string"}],"name":"ExecHello","type":"event"}];

//コントラクト
var contract = web3.eth.contract(abi).at(address);

//監視対象のイベント取得
event = contract.ExecHello();

//監視
event.watch(function(error, result){
    console.log("Event Executed");
    if(!error) console.log(result);
});
```
#### 発火

Eventを検知すると下記のようなログが出力されます。

```bash
Edit event detected!
{ address: '0x4c2bf9b6ae51ee28f53d2e1d5786c2bc3addbab1',
  blockNumber: 21664,
  transactionHash: '0x5029fb148116bfaafc6555a549ab8d184f28c3096dfffc9283cc129205b97c35',
  transactionIndex: 0,
  blockHash: '0x44655fa117f4cf2c58e75f9ec7ecb980d1bf45e9c4df5cf528ef88863ee4df8b',
  logIndex: 0,
  removed: false,
  event: 'ExecHello',
  args:
   { from: '0x08a59abe71e43f9316f34c6d1c924d1414f8d544',
     operation: 'Exec Hello!' } }
```