概要
go-loom
ライブラリには、Goアプリ構築に必要な全てのもの、そしてLoom DAppチェーンと対話するためのサービスが含まれている。これらはDAppチェーン上で機能するスマートコントラクトの構築を可能にする。
go-loom
のインストール:
go get github.com/loomnetwork/go-loom
このセクションではgo-loom
の紹介を行なっていこう。go-loom APIは、Loom DAppチェーンと対話するGoのコードを書くために使用するものだ。Goでのスマートコントラクトのコーディングは、後のセクションで扱っていこう。
go-loom
パッケージには多くのサンプルがある。examples/cli
にはCLI アプリが含まれており、これはスマートコントラクトexamples/plugins/helloworld
と対話するために使用することができる。 まずはCLIアプリの構築及びテスト運用からスタートし、その後構築に使用したgo-loom
APIを紹介していこう。
# これは実行可能な ./example-cli を生成する
make example-cli
CLI アプリのサンプル
helloworldスマートコントラクトは、パブリックなSetMsg
メソッドを持っており、これはキーとバリューの連想配列を保存するよう呼び出すことができる。
./example-cli call set_msg -k 123 -v 456 --contract [contract_name] -p [priv_key]
このスマートコントラクトは同じくパブリックなGetMsg
メソッドを持っており、これはキーとバリューの連想配列を参照するために呼び出すことができる。
./example-cli call get_msg -k 123 -p [priv_key]
以下のレスポンスが見られるはずだ:
{
Key: '123',
Value: '456'
}
これでサンプルCLIアプリの機能のデモンストレーションが完了した。今度はこの実装に使用したgo-loom
APIについて見ていこう。
DAppチェーンへの接続
client.Contract
タイプは、Loom DAppチェーン上で実行されるスマートコントラクトと対話するための便利な方法を提供する。 Loom SDKのサンプルスマートコントラクト helloworld と対話する client.Contract
インスタンスを作成する関数を書いてみよう。
package main
import (
"github.com/loomnetwork/go-loom/auth"
"github.com/loomnetwork/go-loom/client"
"github.com/loomnetwork/go-loom/examples/types"
"golang.org/x/crypto/ed25519"
)
// getContractは新しい`Contract`インスタンスを作成し、これを使ってスマートコントラクトとの対話が行える。
func getContract(contractName string) (*client.Contract, error) {
rpcClient := client.NewDAppChainRPCClient(
"default",
"http://localhost:46658/rpc",
"http://localhost:46658/query",
)
contractAddr, err := rpcClient.Resolve(contractName)
if err != nil {
return nil, err
}
return client.NewContract(rpcClient, contractAddr.Local), nil
}
DAppチェーンへのデータの書き込み
スマートコントラクトの状態を変更するには、そのパブリックなメソッドのうちどれかを呼び出すことが必要であり、さらに署名済みのトランザクションが送信され、DAppチェーンによって検証されていなくてはならない。 幸いこれらのほとんどは、Contract.Call()
メソッドを使用すれば client.Contract
クラスが処理を行う。
helloworldスマートコントラクトは、パブリックなSetMsg
メソッドを持っており、これはキーとバリューの連想配列を保存するよう呼び出すことができる。 このメソッドを呼び出す関数を書いてみよう。
func store(contract *client.Contract, key, value string, signer auth.Signer) error {
params := types.MapEntry{
Key: key,
Value: value,
}
if _, err := contract.Call("SetMsg", ¶ms, signer, nil); err != nil {
return err
}
return nil
}
DAppチェーンからのデータの読み取り
スマートコントラクトの状態を読み取るためには、パブリックな読み取り専用メソッドのうちどれかを呼び出す必要があり、Contract.StaticCall()
メソッドを使って行うことができる。
helloworldスマートコントラクトは、パブリックなGetMsg
メソッドを持っており、キーとバリューの連想配列を参照するようこれを呼び出すことができる。 このメソッドを呼び出す関数を書いてみよう。
func load(contract *client.Contract, key string) (string, error) {
params := types.MapEntry{
Key: key, // The smart contract will look up the value stored under this key.
}
var result types.MapEntry
if _, err := contract.StaticCall("GetMsg", ¶ms, contract.Address, &result); err != nil {
return "", err
}
return result.Value, nil
}
まとめ
全て準備が整ったので、DAppチェーンが稼働していることを確認してから、次のコードを実行してみよう。Value: hello!
とコンソールにプリントされるはずだ。
func main() {
_, privateKey, err := ed25519.GenerateKey(nil)
if err != nil {
panic(err)
}
signer := auth.NewEd25519Signer(privateKey)
contract, err := getContract("helloworld")
if err != nil {
panic(err)
}
store(contract, "123", "hello!", signer)
value, err := load(contract, "123")
if err != nil {
panic(err)
}
fmt.Printf("Value: %s\n", value)
}