Use go to interact with smart contracts and use abigen to generate contract go files for calling

In the first two articles, we explained how go interacts with smart contracts through function selectors and abi calls. Is there a more convenient way (like calling a pre-defined method) to interact with smart contracts? The answer is yes, in this chapter we will learn how to use abigen to generate a contract go file and call it

Courses in this series:

Section 1: Function selector call for interacting with smart contracts using go

Section 2: Abi call using go to interact with smart contracts

Section 3: Use go to interact with smart contracts and use abigen to generate contract go files for calling

1. Configuration environment

1. Install  go-ethereum

 First of all, we need to install  go-ethereum . This article is operated under the windows system. The operation steps of other systems are basically similar. You can refer to the installation by yourself

 After the download is complete, you can directly install it in the default/custom directory. After the installation is complete, we open the installation directory, and you can see that there are many executable files with the .exe suffix

 2. Configure environment variables

Right-click on My Computer-"Advanced System Settings-"Environment Variables-"System Variables, find the Path variable, and then click the Edit button to add the installation directory we just made, as follows:

Then we open the command line terminal, shortcut key: windows+R, enter cmd, and press Enter

The correct output of the installed version number proves that our environment variables have been configured successfully

2. Generate go files through abigen

1. Prepare the abi.json generated after the smart contract is compiled

(This article uses the standard ERC20 contract as an example. If you don’t know how to generate it, you can follow the official account and private message me)

[
  {
    "inputs": [],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Approval",
    "type": "event"
  },
  ……
]

 2. Generate go files through abigen

2.1, we first open a command line terminal, and then the path first jumps to our abi.json storage directory

2.2. Enter the following command in the command line terminal:

abigen --abi abi.json --pkg main --type Token --out Token.go

--abi abi.json is the source file path we want to generate the go file through abigen

--pkg main is the package name in the go file we want to generate (the first line of code in the generated go file such as: package main)

 --type Token generates the components of operable objects/methods/variables in the go file for us. For example, what I wrote here is Token, then the code format in the generated go file is roughly as follows:

As you can see, whether it is a structure, method, or variable, it will be named after this name

--out Token.go is the name of the generated go file (ps: if this command is omitted, the content of the generated go file will be printed on the command line terminal)

After we execute this command, we can see that there is an additional Token.go file in the current directory. Let’s open it and have a look:

// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.

package main

import (
	"errors"
	"math/big"
	"strings"

	ethereum "github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/accounts/abi"
	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/event"
)

// Reference imports to suppress errors if they are not otherwise used.
var (
	_ = errors.New
	_ = big.NewInt
	_ = strings.NewReader
	_ = ethereum.NotFound
	_ = bind.Bind
	_ = common.Big1
	_ = types.BloomLookup
	_ = event.NewSubscription
	_ = abi.ConvertType
)

// TokenMetaData contains all meta data concerning the Token contract.
var TokenMetaData = &bind.MetaData{
	ABI: "……"
}
var TokenABI = TokenMetaData.ABI

// Token is an auto generated Go binding around an Ethereum contract.
type Token struct {
	TokenCaller     // Read-only binding to the contract
	TokenTransactor // Write-only binding to the contract
	TokenFilterer   // Log filterer for contract events
}
func (_Token *TokenSession) BalanceOf(account common.Address) (*big.Int, error) {
	return _Token.Contract.BalanceOf(&_Token.CallOpts, account)
}
func (_Token *TokenTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
	return _Token.Contract.contract.Transfer(opts)
}
…………

It can be seen that there are many structures defined in it and the methods we define in the contract have specific implementations in the go file. In fact, abigen helps us convert the methods defined in our contract into methods that can be directly called by go. thus simplifying our operation

3. The smart contract go file generated by using go call

1. Install go-ethereum

go get -u github.com/ethereum/go-ethereum

2. Create a new main.go file and add dependencies

	"context"
	"fmt"
	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/ethclient"
	"math/big"
	"os"

3. Define constants

const (
	privateKey      = "你的钱包私钥"
	contractAddress = "调用合约地址"
	toAddress       = "接收转账地址" //这里我使用transfer方法作为案例,所以需要一个接收转账地址
)

4. Call demo

4.1. New main method

func main() {}

 4.2. Create ethclient object

client, err := ethclient.Dial("https://goerli.infura.io/v3/3214cac49d354e48ad196cdfcefae1f8")
if err  != nil {
	fmt.Println("ethclient.Dial error : ", err)
	os.Exit(0)
}

4.3. Create smart contract objects

The NewToken here is actually a method in the Token.go file we generated. By passing the contract address and the ethclient object, it will help us create a contract object. Through this contract object, we can easily call the one defined in the contract. Various methods

token, err := NewToken(common.HexToAddress(contractAddress), client)
if err != nil {
	fmt.Println("NewToken error : ", err)
}

4.4. Method call

4.4.1, call method demonstration

The call method is mainly used to call the query method of the smart contract (that is, does not modify the data on the chain and does not spend gas )

Here, we are calling the TotalSupply method of the smart contract, which will return the total supply of the smart contract

totalSupply, err := token.TotalSupply(nil)
if err != nil {
	fmt.Println("token.TotalSupply error : ", err)
}
fmt.Println("totalSupply is : ", totalSupply)

As you can see, the console successfully prints out the return information

4.4.2, send method demonstration

The send method is mainly used to call the method in the smart contract that will modify the data on the chain ( costing gas

Let's take the Transfer method as an example to perform a transfer operation between accounts:

	// 获取当前区块链的ChainID
	chainID, err := client.ChainID(context.Background())
	if err != nil {
		fmt.Println("获取ChainID失败:", err)
		return
	}
	privateKeyECDSA, err := crypto.HexToECDSA(privateKey)
	if err != nil {
		fmt.Println("crypto.HexToECDSA error ,", err)
		return
	}

	gasTipCap, _ := client.SuggestGasTipCap(context.Background())

	//构建参数对象
	opts, err := bind.NewKeyedTransactorWithChainID(privateKeyECDSA, chainID)
	if err != nil {
		fmt.Println("bind.NewKeyedTransactorWithChainID error ,", err)
		return
	}
	//设置参数
	opts.GasFeeCap = big.NewInt(108694000460)
	opts.GasLimit = uint64(100000)
	opts.GasTipCap = gasTipCap

	amount, _ := new(big.Int).SetString("100000000000000000000", 10)
	//调用合约transfer方法
	tx, err := token.Transfer(opts, common.HexToAddress(toAddress), amount)
	if err != nil {
		fmt.Println("token.Transfer error ,", err)
		return
	}

	fmt.Println("使用go调用智能合约第三讲:transfer tx : ", tx.Hash().Hex())

The hash value is returned successfully, let's go to the block chain browser to have a look 

 

It can be seen that the transaction on the chain has been completed

So far, the tutorials on using go and smart contracts are all completed, have you learned it yet? It doesn't matter if you don't learn it, do it twice, practice makes perfect, you can do it too! If you have any questions during the learning process, please leave me a message. In addition, the official account will also share cutting-edge information about blockchain and web3 from time to time. Interested friends can stay tuned

 Please pay attention to the official account: Web3_preacher ( web3_preacher ) , reply "go contract call" to receive the complete code

Guess you like

Origin blog.csdn.net/rao356/article/details/132035372