RPC

Go Client for the Tezos RPC

Visit the GoDoc docu or read the source code on Github.

GoDoc

The RPC package defines a common client object that wraps a HTTP/TLS connection and offers an extensive list of RPC calls to

  • query the state of a Tezos node (GetStatus() and GetVersionInfo())

  • fetch blocks and operations (GetBlock(), GetBlockHeader(), GetBlockOperation(), etc)

  • fetch mempool contents (GetMempool())

  • monitor for events (MonitorBlockHeader(),MonitorMempool(), etc)

  • query accounts, delegates and contract state (e.g. GetContract(), GetDelegate(), GetContractStorage(), GetBigmapValue(), etc)

  • query delegate baking rights, rolls, snapshots

  • query voting data such as lists of voters, ballots, proposals and voting stats

  • run/simulate code, views, operations and broadcast operations

Note that the Tezos RPC uses the term contract for both accounts and smart contracts in its path arguments. To avoid confusion we use the same terminology here.

RPC client

TzGo does not ship a list of public RPC endpoints or a default setting. To create an RPC client you need to provide a URL to either your own node or a public Tezos RPC provider.

// init RPC client with a custom testnet URL
c, _ := rpc.NewClient("https://rpc.hangzhou.tzstats.com", nil)

// optionally fetch the chain configuration; this populates c.Params
// and c.ChainId which is required for some high-level features;
// it also tells you whether the RPC endpoint work or not
err := c.Iinit(ctx)
if err != nil {
  log.Fatalln(err)
}

Customized RPC

TzGo's rpc.NewClient() function takes an optional Go http.Client as parameter which you can configure before or after passing it to the library. The example below shows how to set custom timeouts and disable TLS certificate checks (not recommended in production, but useful if you use self-signed certificates during testing).

import (
  "crypto/tls"
  "log"
  "net"
  "net/http"

  "blockwatch.cc/tzgo/rpc"
)


func main() {
  hc := &http.Client{
    Transport: &http.Transport{
      Dial: (&net.Dialer{
        Timeout:   2 * time.Second,
        KeepAlive: 180 * time.Second,
      }).Dial,
      TLSClientConfig: &tls.Config{
        InsecureSkipVerify: true,
      }
    }
  }

  c, err := rpc.NewClient("https://my-private-node.local:8732", hc)
  if err != nil {
    log.Fatalln(err)
  }
}

Node status

TzGo lets you easily check node status and version

// status info
GetChainId()     // network id
GetStatus()      // node sync status
GetVersionInfo() // node version

Identifying blocks

Many queries in TzGo's RPC package allow you to select a block to run the query against. That way you can access historic state of accounts, contracts or bigmaps if you execute the query against a full archive node. TzGo provides several ways to express block identity using

  • rpc.BlockLevel for block heights (this may be ambiguous during reorgs)

  • rpc.Head or rpc.Genesis as alias names

  • a tezos.BlockHash (is best choice)

  • rpc.BlockOffset to define a positive or negative offset from a given identity

// a hash as block id
hash := tezos.MustParseHash("BM3Y475mu61aTrTgpPdzU7EQVP8T9cReGBuqSU5wEht2gmSN5Ro")

// a block level
lvl := rpc.BlockLevel(2019913)

// positive block offset, e.g. 10 blocks after block BM3Y475...
after := rpc.NewBlockOffset(hash, 10)

// negative block offset, e.g. 10 blocks behind Head
before := rpc.NewBlockOffset(rpc.Head, -10)

Block contents

Tezos blocks contain receipts for confirmed operations plus some consensus-related metadata. A block's identity is uniquely defined by its block hash. The position inside the chain is defined by the block's level and relations between blocks are expressed by a predecessor hash in each block's metadata. Following predecessor hashes backwards walks the entire chain back in history. Block queries can use different identifiers to select a block (see above).

Operations inside a block are assigned to 4 lists according to their type (0) consensus, (1) voting, (2) special and (3) user transactions. An operation in Tezos contains a common header that defines provenance information plus some non-empty content which may be a single transaction or a list of multiple transactions. Transactions are typed and each type contains data that has been sent and signed by a user's wallet plus metadata that has been added as an execution receipt by the Tezos blockchain. Receipts contain balance updates for transfers and fee payments as well as a result which lists all state changes in response to the execution of a transaction. Some smart contract calls can initiate calls to other contracts. If that's the case, an additional internal result list is present.

TzGo's RPC client offers several functions to query blocks, operations and follow the chain of blocks (a non-exhaustive list):

// query block contents (/chains/main/blocks/:id)
GetBlock()                     // single block including all operations
GetBlockHeader()               // single block header only
GetBlockHash()                 // single block hash

// query block hashes (/chains/main/...)
GetTips()                      // list most recent block hashes, first is head
GetBlockPredHashes()           // list predecessor hashes starting at a given block
GetInvalidBlocks()             // list recent invalid blocks (side-chains)
GetInvalidBlock()              // single invalid block

// query operation hashes (/chains/main/blocks/:id/operation_hashes/*/*)
GetBlockOperationHashes()      // all hashes from all lists
GetBlockOperationListHashes()  // all hashes from a given list
GetBlockOperationHash()        // single hash

// query operations contents (/chains/main/blocks/:id/operations/*/*)
GetBlockOperations()           // all operations from all lists
GetBlockOperationList()        // all operations from a given list
GetBlockOperation()            // single operation

In addition, TzGo's RPC client supports calls to stream new blocks and mempool data.

// streaming events
MonitorBootstrapped()    // wait for node to finish initial sync
MonitorBlockHeader()     // stream new block headers (also during reorgs)
MonitorMempool()         // stream new operations entering the mempool

Account and contract state

Blocks represent the history of updates, but many applications require the current state of an account or some historic state in the past. Both is possible by using a BlockID, for the current block use the rpc.Head constant, for a historic block use its hash or level.

Note Tezos RPC paths do not distinguish between end user accounts (tz1/tz2/tz3) and smart contracts (KT1), and account calls are named 'contract'. The TzGo client exports the following functions to query account data.

# query accounts (/chains/main/blocks/:id/context/contracts/:address)
GetContract()               // account info (balance, counter, delegate)
GetContractScript()         // smart contract code
GetContractStorage()        // smart contract storage
GetContractEntrypoints()    // smart contract entrypoints

# query bakers (/chains/main/blocks/:id/context/delegates/:address)
GetDelegate()               // baker info (balances, delegators)
ListActiveDelegates()       // addresses of active bakers

# query bigmap data (/chains/main/blocks/:id/context/big_maps/:ptr)
GetBigmapInfo()             // key/value types and size
GetBigmapValue()            // single value (Micheline primitives)
ListBigmapKeys()            // SLOW (!) list all key expr hashes
ListBigmapValues()          // SLOW (!) list all values (Micheline primitives)

TzGo supports a few more calls specific to baker accounts which allow you to list baking rights and governance voting

// baker rights (chains/main/blocks/:id/helpers/baking_rights and ./endorsing_rights)
ListBakingRights()            // single block
ListBakingRightsCycle()       // full cycle
ListEndorsingRights()         // single block
ListEndorsingRightsCycle()    // full cycle
GetSnapshotIndexCycle()       // snapshot block info, works pre/post Ithaca
GetRollSnapshotInfoCycle()    // pre-Ithaca only
GetStakingSnapshotInfoCycle() // post-Ithaca only
ListSnapshotRollOwners()      // baker key list per roll, pre-Ithaca only

// voting (chains/main/blocks/:id/votes/...)
GetVoteQuorum()      // required quorum at voting period
GetVoteProposal()    // winning proposal
ListBallots()        // all ballots at voting period
ListProposals()      // all proposals at voting period
GetVoteResult()      // current status or final result 

Sending Operations

TzGo supports sending of all operation kinds including batch operations (operation groups). The typical Tezos flow of sending an operation constructed by the codec or contract packages is

  1. Fill an operation or group with the desired content

  2. Define a block as anchor (branch) to control the maximum lifetime should the operation remain unconfirmed

  3. Complete the operation by dynamically adding a reveal operation to publish the signere's public key if necessary

  4. Simulate the operation to identify errors early and to estimate costs (gas and storage)

  5. Fill in costs and fees

  6. Serialize and sign the operation

  7. Inject (broadcast) the signed operation

  8. Wait for confirmation (inclusion in a block plus at least N blocks on top to be reorg safe)

Each step of the process can be executed individually step by step using available methods. Most of the time its, however, more convenient to just call Send()

// hight-level operation for sending operations defined by RPC client
Complete()     // adds reveal, sets counters, adds branch if missing
Simulate()     // dry-run the operation to identify costs and catch errors
Validate()     // check local serialization against Tezos node (optional)
Broadcast()    // inject operation into the network
Send()         // all-in-one wrapper complete/simulate/broadcast/wait

// additional low-level RPC helpers
BroadcastOperation()     // inject signed binary data (low-level)
ForgeOperation()         // serialized operation data remotely
RunOperation()           // simulate an operation (low-level)
RunCode()                // execute off-chain view or other code
RunView()                // execute on-chain view
TraceCode()              // debug tracing contract code

Call Options

The Send() and Simulate() functions on the RPC client take an optional argument CallOptions as the last parameter which can be used for customizing the behavior per call.

type CallOptions struct {
  // number of confirmations to wait after broadcast
  Confirmations int64         
  // max acceptable fee, optional (default = 0)
  MaxFee        int64         
  // max lifetime for operations in blocks
  TTL           int64         
  // ignore simulated limits and use user-defined limits from op.WithLimits()
  IgnoreLimits  bool          
  // custom signer to use for signing the transaction
  Signer        signer.Signer 
  // custom address to sign for (use when signer manages multiple addresses)
  Sender        tezos.Address 
  // custom block observer for waiting on confirmations
  Observer      *Observer     
}

Call Receipts

The execution result of a finalized operation is wrapped into a Receipt struct

type Receipt struct {
	Block tezos.BlockHash // block the operation was included in
	List  int             // operation list (alwasy 3 for regular transactions)
	Pos   int             // list position
	Op    *Operation      // RPC operation receipt
}

// convenience wrappers on receipt
TotalCosts()   // summarized gas/storage/burn/fees 
Costs()        // array of individual gas/storage/burn/fees
IsSuccess()    // true when all contained operations are applied
Error()        // returns the first (non-backtracked) error
MinLimits()    // array of gas/storage limits (returned by simulation)

Last updated