Contract

Smart contract and token calls

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

Package contract simplifies working with smart contracts and FA tokens. It also allows you to batch several contract calls into the same transaction.

Deploy

Simply load a script from file or another way and deploy it as new a contract

import (
    "context"
    "blockwatch.cc/tzgo/codec"
    "blockwatch.cc/tzgo/rpc"
)

// assuming you have an initialized RPC client and a loaded script
con := contract.NewEmptyContract(client).WithScript(script)

// deploy in a single call (which will simulate, sign, broadcast and wait)
rcpt, err := con.Deploy(ctx, nil)
  
// then access the new address
addr := con.Address()

// and get deployment cost
cost := rcpt.TotalCost()

For situations where you also want to transfer tez or set an initial delegate with the origination, use con.DeployExt()

Call

Assembling calls for smart contracts is also easy. Use the micheline package to construct custom call parameters from

type Parameters struct {
  Entrypoint string `json:"entrypoint"`
  Value      Prim   `json:"value"`
}

then use these parameters to make a call like

// construct call arguments
args := contract.NewTxArgs().
  WithParameters(micheline.Parameters{Entrypoint:"transfer", Value: prim})
  WithSource(sender).            // optional sender (also added when signing)
  WithAmount(tezos.N(1_000_000)) // optional amount in tez to send with call

// then execute the call with default options
rcpt, err := con.Call(ctx, args, nil)

Its also possible to batch multiple TxArgs into a single transaction with con.CallMulti()

Tokens

If you work with token contracts that implement any of the TZIP standard FA1.2 or FA2 you can use the provided token wrappers to automatically generate call parameters. You may also add A simple FA2 transfer can be implemented as

import (
    "context"
    "blockwatch.cc/tzgo/contract"
    "blockwatch.cc/tzgo/rpc"
    "blockwatch.cc/tzgo/signer"
    "blockwatch.cc/tzgo/tezos"
)

// create an RPC client
c, _ := rpc.NewClient("https://rpc.tzstats.com", nil)

// use private key to sign
c.Signer = signer.NewFromKey(tezos.MustParsePrivateKey("SK..."))

// constuct a new contract
con := contract.NewContract(tezos.MustParseAddress("KT1..."), c)

// construct an FA2 token wrapper (use token id 0)
fa2token := con.AsFA2(0)

// construct simple transfer arguments
args := fa2token.Transfer(
    tezos.MustParseAddress("tz..."), // from
    tezos.MustParseAddress("tz..."), // to
    tezos.NewZ(1_000_000),           // amount
)

// execute the call (will complete reveal, simulate cost, add cost, sign, broadcast, wait)
rcpt, _ := con.Call(ctx, args, nil)

In more complex scenarios you can add multiple transfers to the same FA2 transfer list

// construct complex transfer args
args := contract.NewFA2TransferArgs().
  WithTransfer(from_1, to_2, token_id_1, amount_1).
  WithTransfer(from_2, to_2, token_id_2, amount_2).
  Optimize() // optional, optimize args (for minimal parameter size)

// execute the call
rcpt, _ := con.Call(ctx, args, nil)

or you can batch multiple calls

// append multiple calls (silly example, but you get the point)
args := []contract.CallArguments{
    fa2token.AddOperator(owner, operator),
    fa2token.Transfer(from, to, amount),
    fa2token.Transfer(from, to, amount),
    fa2token.RemoveOperator(owner, operator),
}

// execute all calls in a single batch transaction
rcpt, _ := con.CallMulti(ctx, args, nil)

Last updated