solidityのコントラクトをJavaのコントラクトクラスに変換する方法

# 記事の内容
solidityで使ったコントラクトをweb3jで使用する場合、コントラクトを操作するためのJavaのクラスを使用する必要があります。

一からこのコントラクトを操作するクラスを作成することはもちろん可能ですが、簡単に作成する方法があったのでメモを残します。

# 環境
- solidity:v0.4.24
- solc:0.4.24+commit.6ae8fb59.Windows.msvc
- jdk:1.8
- web3j:4.5.0
- OS:Windows10

# Web3jのダウンロード
コマンドラインでsolファイルをjavaファイルに変換するツールが提供されているので、ダウンロードします。

[web3j](https://github.com/web3j/web3j/releases/tag/v4.5.0)

1. リンク先にzipファイルがあるのでダウンロードします。
2. zipファイルを解凍し、任意のディレクトリに配置します。
3. 配置したディレクトリのbinディレクトリへパスを通します。
4. コマンドプロンプトで「web3j」と入力します。

以下の表示が出れば設定完了です。

```

              _      _____ _     _
             | |    |____ (_)   (_)
__      _____| |__      / /_     _   ___
\ \ /\ / / _ \ '_ \     \ \ |   | | / _ \
 \ V  V /  __/ |_) |.___/ / | _ | || (_) |
  \_/\_/ \___|_.__/ \____/| |(_)|_| \___/
                         _/ |
                        |__/
Usage: web3j version|wallet|solidity ...
```

# binファイルとabiファイルを作成する

まずは、solファイルを用意します。

``` addition.sol
pragma solidity ^0.4.24;

contract Addition{
  int num = 0;
  function add(int a) public {
    num += a;
  }
  function get() public view returns(int)  {
    return num;
  }
}
```

このsolファイルをコンパイルし、binとabiを取り出します。

```
solc --bin addition.sol > addition.bin
solc --abi addition.sol > addition.abi
```

それぞれ出力されるファイルは以下のとおりとなります。

``` addition.bin
======= addition.sol:Addition =======
Binary: 
60806040526000805534801561001457600080fd5b5060e7806100236000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636d4ce63c14604e57806387db03b7146076575b600080fd5b348015605957600080fd5b50606060a0565b6040518082815260200191505060405180910390f35b348015608157600080fd5b50609e6004803603810190808035906020019092919050505060a9565b005b60008054905090565b806000808282540192505081905550505600a165627a7a723058200522274b97a5967f28327168f4654fbd3921238ed6de8e155c966f7dad168e020029
```

``` addition.abi
======= addition.sol:Addition =======
Contract JSON ABI 
[{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"a","type":"int256"}],"name":"add","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
```

この２ファイルですが、最初の数行（~Binary:まで／~JSON ABIまで）はこれからの処理に不要な内容になるので、削除しておきます。

# コントラクトクラスを作成する

以下のコマンドで作成します

```
web3j solidity generate -a=addition.abi -b=addition.bin -o=src -p=jp.ethereum.contracts
```
実行結果

```

              _      _____ _     _
             | |    |____ (_)   (_)
__      _____| |__      / /_     _   ___
\ \ /\ / / _ \ '_ \     \ \ |   | | / _ \
 \ V  V /  __/ |_) |.___/ / | _ | || (_) |
  \_/\_/ \___|_.__/ \____/| |(_)|_| \___/
                         _/ |
                        |__/

Generating jp.ethereum.contracts.Addition ... File written to src
```

この結果が出れば出力が完了です。
「-O」オプションで指定したディレクトリに出力されます。
この場合だと、srcディレクトリ配下に「-p」で指定した「jp.ethereum.contracts」パッケージを作成し、その配下にAddtion.javaが作成されます。

``` addtion.java
package jp.ethereum.contracts;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Int256;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.protocol.core.RemoteFunctionCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.ContractGasProvider;

/**
 * <p>Auto generated code.
 * <p><strong>Do not modify!</strong>
 * <p>Please use the <a href="https://docs.web3j.io/command_line.html">web3j command line tools</a>,
 * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the 
 * <a href="https://github.com/web3j/web3j/tree/master/codegen">codegen module</a> to update.
 *
 * <p>Generated with web3j version 4.5.0.
 */
public class Addition extends Contract {
    private static final String BINARY = "60806040526000805534801561001457600080fd5b5060e7806100236000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636d4ce63c14604e57806387db03b7146076575b600080fd5b348015605957600080fd5b50606060a0565b6040518082815260200191505060405180910390f35b348015608157600080fd5b50609e6004803603810190808035906020019092919050505060a9565b005b60008054905090565b806000808282540192505081905550505600a165627a7a723058200522274b97a5967f28327168f4654fbd3921238ed6de8e155c966f7dad168e020029\r\n";

    public static final String FUNC_GET = "get";

    public static final String FUNC_ADD = "add";

    @Deprecated
    protected Addition(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
    }

    protected Addition(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
        super(BINARY, contractAddress, web3j, credentials, contractGasProvider);
    }

    @Deprecated
    protected Addition(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
        super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
    }

    protected Addition(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
        super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider);
    }

    public RemoteFunctionCall<BigInteger> get() {
        final Function function = new Function(FUNC_GET, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Int256>() {}));
        return executeRemoteCallSingleValueReturn(function, BigInteger.class);
    }

    public RemoteFunctionCall<TransactionReceipt> add(BigInteger a) {
        final Function function = new Function(
                FUNC_ADD, 
                Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.Int256(a)), 
                Collections.<TypeReference<?>>emptyList());
        return executeRemoteCallTransaction(function);
    }

    @Deprecated
    public static Addition load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        return new Addition(contractAddress, web3j, credentials, gasPrice, gasLimit);
    }

    @Deprecated
    public static Addition load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
        return new Addition(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
    }

    public static Addition load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
        return new Addition(contractAddress, web3j, credentials, contractGasProvider);
    }

    public static Addition load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
        return new Addition(contractAddress, web3j, transactionManager, contractGasProvider);
    }

    public static RemoteCall<Addition> deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
        return deployRemoteCall(Addition.class, web3j, credentials, contractGasProvider, BINARY, "");
    }

    @Deprecated
    public static RemoteCall<Addition> deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        return deployRemoteCall(Addition.class, web3j, credentials, gasPrice, gasLimit, BINARY, "");
    }

    public static RemoteCall<Addition> deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
        return deployRemoteCall(Addition.class, web3j, transactionManager, contractGasProvider, BINARY, "");
    }

    @Deprecated
    public static RemoteCall<Addition> deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
        return deployRemoteCall(Addition.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, "");
    }
}
```

このクラスはWeb3jを使用しコントラクトを実行する際に必要となります。
非推奨となっているメソッドが多数存在しますので、使用する際は注意が必要です。

# 参考

[web3j docs](https://web3j.readthedocs.io/en/latest/smart_contracts.html)