On the local Ethereum private chain, use go to call the smart contract and get the event log

1. Please refer to the previous article about the development environment construction configuration, etc.
2. Deploy the contract code erc20.js

const hre = require("hardhat");
async function main() {
  const CONTRACT = await hre.ethers.getContractFactory("ERC20");

  const contract = await CONTRACT.deploy();
  await contract.init("ERC20Name","ERC20Symbol");
  console.log("name:",contract.name(),"symbol:",contract.symbol());
  await contract.deployed();

  console.log(`contract deployed to ${contract.address}`);
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

3. Start and upload

#切换到智能合约项目位置
npx hardhat node
#新开一个窗口,确保localhost已经在hardhat.config.js中配置了,可查看第一步链接对照
npx hardhat run scripts/erc.js --network localhost


4. Create a new folder, store the go project, complete the mod initialization, etc.

Complete go project file directory


5. Copy the ABI generated by the smart contract compile, and create a new erc20.json file in the new folder

 

 

6. Install abigen

go get github.com/ethereum/go-ethereum

#切换路径 cd $GOPATH/pkg/mod/github.com/ethereum/[email protected]
sudo make && make devtools

#测试安装
abigen --help

7. Generate ABI into GO file

abigen --abi erc20.json -pkg json -type erc20 --out erc20.go

8. Write the calling file main.go

package main

import (
	"context"
	"crypto/ecdsa"
	"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"
	"mysolidity/json"
)

func main() {
	//合约地址
	contractAddress := "0x5FbDB2315678afecb367f032d93F642f64180aa3"
	//连接本地的以太坊私链(一定要保证本地以太坊私链已经启动)
	conn, err := ethclient.Dial("http://127.0.0.1:8545")
	fmt.Println("connect to local node...", conn)
	if err != nil {
		fmt.Errorf("could not connect to local node: %v", err)
		return
	}
	//创建合约
	erc20, err := json.NewErc20(common.HexToAddress(contractAddress), conn)
	if err != nil {
		fmt.Errorf("failed to instantiate a Token contract: %v", err)
		return
	}
	fmt.Println("contract token:", erc20)
	//调用合约查询方法
	name, err := erc20.Name(&bind.CallOpts{
		Pending:     false,
		From:        common.Address{},
		BlockNumber: nil,
		Context:     nil,
	})
	if err != nil {
		fmt.Errorf("name:%v", err)
		return
	}
	symbol, err := erc20.Symbol(&bind.CallOpts{
		Pending:     false,
		From:        common.Address{},
		BlockNumber: nil,
		Context:     nil,
	})
	if err != nil {
		fmt.Errorf("name:%v", err)
		return
	}
	fmt.Println("name:", name, "symbol:", symbol)
	//查询第一个账户余额
	b, err := erc20.BalanceOf(&bind.CallOpts{
		Pending:     false,
		From:        common.Address{},
		BlockNumber: nil,
		Context:     nil,
	}, common.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"))//启动node默认生成的第1个账户地址
	if err != nil {
		fmt.Errorf("BalanceOf:%v", err)
		return
	}
	fmt.Println("first balance:", b)
	第一个账户给第二个账户转账
	//私钥,需要生成签名
	privateKey, err := crypto.HexToECDSA("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80")//私钥注意去掉ox,这是启动node默认生成的第1个账户的私钥
	if err != nil {
		fmt.Errorf("err:%v\n", err)
		return
	}
	publicKey := privateKey.Public()
	publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
	if !ok {
		fmt.Errorf("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
		return
	}
	fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
	nonce, err := conn.PendingNonceAt(context.Background(), fromAddress)
	if err != nil {
		fmt.Errorf("%v", err)
		return
	}
	gasPrice, err := conn.SuggestGasPrice(context.Background())
	if err != nil {
		fmt.Errorf("%v", err)
		return
	}
	//chainID
	id, err := conn.ChainID(context.Background())
	if err != nil {
		return
	}
	fmt.Println("chainID:", id)
	auth, _ := bind.NewKeyedTransactorWithChainID(privateKey, id)
	auth.Nonce = big.NewInt(int64(nonce))
	auth.Value = big.NewInt(10)    
	auth.GasLimit = uint64(300000) 
	auth.GasPrice = gasPrice
	tx, err := erc20.Transfer(&bind.TransactOpts{
		Signer:   auth.Signer,
		From:     fromAddress,
		GasLimit: auth.GasLimit,
		GasPrice: auth.GasPrice,
		Context:  nil,
	}, common.HexToAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8"), big.NewInt(8))
	if err != nil {
		fmt.Errorf("transfer:%v", err)
		return
	}
	fmt.Println("tx.GasPrice():", tx.GasPrice())
	//查询两个账户余额
	b, err = erc20.BalanceOf(&bind.CallOpts{From: fromAddress}, common.HexToAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8"))//启动node默认生成的第2个账户地址
	if err != nil {
		fmt.Errorf("BalanceOf:%v", err)
		return
	}
	fmt.Println("second balance:", b)
	b, err = erc20.BalanceOf(&bind.CallOpts{From: fromAddress}, fromAddress)
	if err != nil {
		fmt.Errorf("BalanceOf:%v", err)
		return
	}
	fmt.Println("first balance:", b)
}

9. Query event log (the general process of complete development, after the smart contract is developed on the chain end, the front end uses web3.js to interact, and the back end modifies the database information display by querying the event log)

package main

import (
	"context"
	"fmt"
	"github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/ethclient"
	"math/big"
	"mysolidity/json"
)

func main() {
	//合约地址
	contractAddress := common.HexToAddress("0x5FbDB2315678afecb367f032d93F642f64180aa3")
	//websocket监听
	client, err := ethclient.Dial("ws://127.0.0.1:8545/ws")
	if err != nil {
		fmt.Errorf("could not connect to local node: %v", err)
		return
	}
	query := ethereum.FilterQuery{
		FromBlock: big.NewInt(1), //生产环境中,从0开始,查询后修改区块记录,下一次就从后一个有记录的区块数开始
		ToBlock:   big.NewInt(100),
		Addresses: []common.Address{
			contractAddress,
		},
	}
	erc20, _ := json.NewErc20(contractAddress, client)
	logs, err := client.FilterLogs(context.Background(), query)
	if err != nil {
		fmt.Errorf("err:%v\n", err)
		return
	}
	for _, vLog := range logs {
		if len(vLog.Topics) == 0 {
			continue
		}
		event := vLog.Topics[0].Hex()
		if event == TransferEvent() { //对对应的事件进行对应的处理
			fmt.Println(vLog.Data)
			data, err := erc20.ParseTransfer(vLog)
			if err != nil {
				fmt.Errorf("err:%v\n", err)
				continue
			}
			fmt.Println(data.From.Hex(), data.To.Hex(), data.Value.Int64(), data.Raw.Data)
		}
	}
}
func TransferEvent() string {
	event := crypto.Keccak256Hash([]byte("Transfer(address,address,uint256)")).Hex()
	return event
}

10. Test results (main.go is the result of the last run)

 

Guess you like

Origin blog.csdn.net/qq_37575994/article/details/127409552