abigenでabiを.goに書き出し

#はじめに
web3jsで作っていたものをgolangで書き直すことになったので、自分用の覚書として残しておきます。
golangでEthereum開発する場合、abigenが必要なのですが、
Goのversionによっては、make devtoolsした時に、エラーになってしまうことがあり、今回は1.12.1で試しています。

#オペレーション

##1.GVM

```
$ bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
$ source ~/.gvm/scripts/gvm 
$ gvm version
```

##2.Go

```
$ gvm listall
$ gvm install go1.12.1
$ gvm use go1.12.1
$ go version
$ echo "             
source ~/.gvm/scripts/gvm
gvm use `gvm list | grep -v gvm | grep -v '^ *$' | tr -d '=>' | tail`
">>~/.bash_profile 
```

##3.go-ethereum
(https://github.com/ethereum/go-ethereum)
ここでabigenなどもインストールされる

```
go get -u github.com/ethereum/go-ethereum
cd $GOPATH/src/github.com/ethereum/go-ethereum/
make && make devtools  
```

##4.fresh

```
$ go get -u github.com/pilu/fresh
$ fresh 
```


##5. echoで雛形を作る

```
//prepare
$ go get -u github.com/labstack/echo/...
$ mkdir $GOPATH/src/github.com/oggata/colorul_api
$ vim $GOPATH/src/github.com/oggata/colorul_api/main.go

//build
$ go fmt github.com/oggata/colorul_api
$ go build github.com/oggata/colorul_api
$ ./colorul_api
$ curl localhost:1323
```

##6. abigenで .abi -> .go Convert

サンプルとしてdemo.sqlを用意してrinkebyにdeployしておきます。.abiはremixからコピペして.abiファイルとして作っておく。

```demo.sol
pragma solidity >=0.5.0;

contract SimpleStorage {
    uint storedData = 12345;

    function set(uint x) public {
        storedData = x;
    }

    function get() public view returns (uint) {
        return storedData;
    }
}
```

```demo.abi
[
	{
		"inputs": [],
		"name": "get",
		"outputs": [
			{
....
```


```
//.abi to .go command
$ abigen --abi demo.abi --pkg demo --type demo --out demo.go
```

ポイントとしては、abigenが作ってくれたdemo.goに、NewDemoというfunctionが出来上がるので、
下記のような形で読んであげて、contractのinstanceを作るという感じです。
さらに、contractの中で"getCardData"という呼び方があるとしたら、abigenで生成された.goの関数名はGetCardDataと頭が大文字になっているため、コードから生成したinstanceでcallするときに、大文字にしてあげないといけない点にちょいハマった。。
他の記述箇所ややっていることはweb3jsなどとほとんど変わらず。

```
//1.インスタンス生成
instance, err := demo.NewDemo(contract-address, client)

//2.method名の頭が大文字
result, err := instance.GetCardData(big.NewInt(1))
```

##7. SimpleStorage.set / SimpleStorage.get
これができれば大体のことはできるはず。。

```contract.go

package controllers
import (
    "net/http"
    "context"
    "crypto/ecdsa"
    "fmt"
    "log"
    "math/big"    
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/accounts/abi/bind"
    "github.com/ethereum/go-ethereum/crypto"
    "github.com/ethereum/go-ethereum/ethclient"
    demo "github.com/aaa/bbb/contracts/demo"
    "github.com/labstack/echo"
)

func ContractRead(c echo.Context) error {
    client, err := ethclient.Dial("https://rinkeby.infura.io/v3/------")
    if err != nil {
        log.Fatal(err)
    }
    privateKey, err := crypto.HexToECDSA("---private key-----")
    if err != nil {
        log.Fatal(err)
    }
    publicKey := privateKey.Public()
    publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
    if !ok {
        log.Fatal("error casting public key to ECDSA")
    }
    fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA) 
    nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
    if err != nil {
        log.Fatal(err)
    }
    gasPrice, err := client.SuggestGasPrice(context.Background())
    if err != nil {
        log.Fatal(err)
    }
    auth := bind.NewKeyedTransactor(privateKey)
    auth.Nonce = big.NewInt(int64(nonce))
    auth.Value = big.NewInt(0)     // in wei
    auth.GasLimit = uint64(300000) // in units
    auth.GasPrice = gasPrice
    address := common.HexToAddress("-----contract address-----")
    instance, err := demo.NewDemo(address, client)
    if err != nil {
        log.Fatal(err)
    }
    tx, err := instance.Set(auth, big.NewInt(123))
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("tx sent: %s", tx.Hash().Hex())
    result, err := instance.Get(&bind.CallOpts{})
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(result)
    return c.JSON(http.StatusOK, tx.Hash().Hex())
}
```

#参考
http://runkiss.blogspot.com/2019/12/deploy-smart-contract-on-ethereum-using.html
https://www.yo1000.com/golang-setup2/