TzGo allows you to work with smart contract data in a straight forward way using regular Go types and without the need to parse through Micheline encoded trees. TzGo can natively process contract scripts, storage, entrypoints, views, call parameters and bigmaps.
With a few notable exceptions (see below), most data is available on the Tezos RPC, so you can use TzGo and a Tezos node to write most parts of an application without the need for an indexer. The following features are unavailable on the Tezos RPC:
lookup of operations by hash
listing of historic transactions from and to an address
listing of blocks where an account update happened
the contents of bigmap keys (the node only stores bigmap key hashes)
listing of bigmap keys and values (this exists, but lacks pagination support)
Fetching and decoding contract storage
import ("blockwatch.cc/tzgo/micheline""blockwatch.cc/tzgo/rpc""blockwatch.cc/tzgo/tezos")// we use the Baker Registry on mainnet as exampleaddr := tezos.MustParseAddress("KT1ChNsEFxwyCbJyWGSL3KdjeXE28AY1Kaog")// init RPC clientc, _ := rpc.NewClient("https://rpc.tzstats.com", nil)// fetch the contract's script and most recent storagescript, _ := c.GetContractScript(ctx, addr)// unfold Micheline storage into human-readable formval := micheline.NewValue(script.StorageType(), script.Storage)m, _ := val.Map()buf, _ := json.MarshalIndent(m, "", " ")fmt.Println(string(buf))
Decoding contract call parameters
import ("blockwatch.cc/tzgo/micheline""blockwatch.cc/tzgo/rpc""blockwatch.cc/tzgo/tezos")// init RPC clientc, _ := rpc.NewClient("https://rpc.tzstats.com", nil)// assuming you have this transactiontx := block.Operations[3][0].Contents[0].(*rpc.TransactionOp)// load the contract's script for type infoscript, err := c.GetContractScript(ctx, tx.Destination)// unwrap params for nested entrypointsep, param, err := tx.Parameters.MapEntrypoint(script.ParamType())// convert Micheline param data into human-readable formval := micheline.NewValue(ep.Type(), param)// e.g. access individual nested fields using value helpersfrom, ok := val.GetAddress("transfer.from")
Listing a contract's bigmaps
import ("blockwatch.cc/tzgo/micheline""blockwatch.cc/tzgo/rpc""blockwatch.cc/tzgo/tezos")// we use the hic et nunc NFT market on mainnet as exampleaddr := tezos.MustParseAddress("KT1Hkg5qeNhfwpKW4fXvq7HGZB9z2EnmCCA9")// init RPC clientc, _ := rpc.NewClient("https://rpc.tzstats.com", nil)// fetch the contract's script and most recent storagescript, _ := c.GetContractScript(ctx, addr)// bigmap pointers as []int64ids := script.BigmapsById()// bigmap pointers as named map[string]int64 (names from type annotations)named := script.BigmapsByName()
Fetching and decoding bigmap values
// init RPC clientc, _ := rpc.NewClient("https://rpc.tzstats.com", nil)// load bigmap type info (use the Baker Registry on mainnet as example)biginfo, _ := c.GetBigmapInfo(ctx, 17)// list all bigmap keysbigkeys, _ := c.GetBigmapKeys(ctx, 17)// visit each valuefor _, key :=range bigkeys { bigval, _ := c.GetBigmapValue(ctx, 17, key)// unfold Micheline type into human readable form val := micheline.NewValue(micheline.NewType(biginfo.ValueType), bigval) m, _ := val.Map() buf, _ := json.MarshalIndent(m, "", " ") fmt.Println(string(buf))}