使用go与智能合约交互之使用abigen生成合约go文件进行调用

前两篇文章,我们讲解了go如何通过函数选择器、abi调用的方式与智能合约交互,那么有没有一种更加便捷的方式(就好像调用预先定义好的方法一样)与智能合约交互呢?答案是有的,本章我们就来学习一下如何使用abigen生成合约go文件并进行调用

本系列课程:

第一节:使用go与智能合约交互之函数选择器调用

第二节:使用go与智能合约交互之abi调用

第三节:使用go与智能合约交互之使用abigen生成合约go文件进行调用

一、配置环境

1、安装 go-ethereum

 首先我们要安装 go-ethereum,本篇文章是在windows系统下操作,其他系统操作步骤基本类似,可自行参考安装

 下载完成之后 直接默认/自定义目录安装即可,安装完成后我们打开安装目录,可以看到里面有很多.exe后缀的可执行文件

 2、配置环境变量

右键我的电脑-》高级系统设置-》环境变量-》系统变量,找到Path这个变量,然后点编辑按钮,在里面添加我们刚刚的安装目录,如下:

然后我们打开 命令行终端,快捷键:windows+R,输入cmd,然后回车

能正确输出安装版本号证明我们环境变量已经配置成功

二、通过abigen生成go文件

1、准备智能合约编译后生成的abi.json

(本文以标准ERC20合约作为示例,不知道怎么生成的可关注公众号私信我)

[
  {
    "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、通过abigen生成go文件

2.1、我们先打开一个命令行终端,然后路径先跳转到我们的abi.json存放目录下

2.2、在命令行终端输入以下命令:

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

--abi abi.json 为我们要通过abigen生成go文件的 源文件路径

--pkg main 为我们要生成go文件里面的包名(生成的go文件第一行代码 如:package main)

 --type Token 为我们生成go文件里可操作对象/方法/变量的组成部分,比如我这里写的是Token,那么生成的go文件里面的代码格式大概如下:

可以看到,里面无论是结构体、方法、变量,均会以该名字进行命名

--out Token.go 为生成go文件的名称 (ps:如果省略此命令,生成的go文件内容会打印在命令行终端上)

我们执行此命令后,可以看到当前目录下多了一个Token.go的文件,我们打开看一下:

// 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)
}
…………

可以看到,里面定义了很多结构体以及我们在合约里定义的方法在go文件里都有具体的实现,其实就是abigen帮我们把我们合约里定义的方法转成了go可以直接调用的方法,从而简化了我们的操作

三、使用go调用生成的智能合约go文件

1、安装go-ethereum

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

2、新建main.go文件,添加依赖

	"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、定义常量

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

4、调用演示

4.1、新建main方法

func main() {}

 4.2、创建ethclient对象

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

4.3、创建智能合约对象

这里的NewToken其实就是我们生成的Token.go文件里的一个方法,通过传递合约地址、ethclient对象,他便会帮我们创建一个合约对象,我们通过这个合约对象就可以很方便调用合约里定义好的各种方法

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

4.4、方法调用

4.4.1、call方法演示

call方法主要用来调用智能合约的查询方法(即不修改链上数据,不花费gas

这里,我们调用的是智能合约的TotalSupply方法,它会返回该智能合约的总供应量

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

可以看到,控制台成功打印出返回信息

4.4.2、send方法演示

send方法,主要用来调用智能合约里会修改链上数据的方法(花费gas) 

我们以Transfer方法为例,进行一笔账号之间的转账操作:

	// 获取当前区块链的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())

成功返回哈希值,让我们去区块链浏览器里看一下 

 

可以看到链上交易已经完成

到此,使用go与智能合约的教程全部完成,你学会了吗?没有学会不要紧,多做两遍,熟能生巧,你一定也可以的!如果在学习过程中有任何问题,欢迎给我留言,另外公众号也会不定期分享关于区块链、web3的前沿信息,感兴趣的朋友可以保持关注

 请关注公众号:外柏叁布道者(web3_preacher,回复 “go合约调用” 领取完整代码

### 使用 Golang 开发智能合约的方法 在区块链领域,Golang 是一种广泛使用的编程语言开发智能合约。以下是关于如何使用 Golang 编写或转换为智能合约的相关信息。 #### 1. 智能合约的基础概念 智能合约是一种用计算机语言编写的程序,用于定义和执行交易的条件、业务逻辑等[^2]。它可以在区块链网络上自动运行并操作账本数据。Fabric 平台中的链码(Chaincode)就是一种典型的智能合约形式,通常由 Golang 实现[^4]。 #### 2. Fabric 中的 Golang 链码开发 Hyperledger Fabric 支持多种语言实现链码,其中 Golang 的性能和稳定性表现优异。开发者可以通过编写 Go 文件来创建链码,并将其部署到区块链网络中。以下是一个简单的例子: ```go package main import ( "fmt" "github.com/hyperledger/fabric-contract-api-go/contractapi" ) type SmartContract struct { contractapi.Contract } func (s *SmartContract) SaveEvidence(ctx contractapi.TransactionContextInterface, key string, value string) error { err := ctx.GetStub().PutState(key, []byte(value)) if err != nil { return fmt.Errorf("failed to save evidence: %v", err) } return nil } func (s *SmartContract) FindEvidence(ctx contractapi.TransactionContextInterface, key string) (*string, error) { valueBytes, err := ctx.GetStub().GetState(key) if err != nil || len(valueBytes) == 0 { return nil, fmt.Errorf("evidence not found with key: %s", key) } valueString := string(valueBytes) return &valueString, nil } func main() { chaincode, err := contractapi.NewChaincode(new(SmartContract)) if err != nil { fmt.Printf("Error creating chaincode: %s", err.Error()) return } server := &contractapi.Server{CCID: "example_cc", Chaincode: chaincode} if err := server.Start(); err != nil { fmt.Printf("Error starting server: %s", err.Error()) } } ``` 上述代码展示了如何通过 Hyperledger Fabric 提供的 `fabric-contract-api-go` 库构建一个基本的存证功能链码[^3]。 #### 3. 将 Golang 转换为 ABI 和接口文件 为了使智能合约能够其他应用程序交互,通常需要生成 ABI(Application Binary Interface)。对于 Ethereum 生态系统,可以利用工具如 abigen 来完成这一过程。具体流程如下: - 编写 Solidity 或其他兼容的语言版本的智能合约。 - 使用 abigen 工具将 ABI 转化为目标语言(如 Go)的绑定文件[^1]。 然而,在 Hyperledger Fabric 场景下,由于其架构设计不同,无需显式生成 ABI 文件。取而代之的是直接提供 API 接口以便外部调用。 #### 4. BSN 上的 Node.js 智能合约开发 虽然题目提到 Golang,但在某些情况下也可以考虑使用 JavaScript 进行开发。例如,在 Blockchain Service Network (BSN) 环境中支持 Node.js 版本的应用开发。尽管如此,如果目标平台更倾向于 Golang,则应优先采用该方式。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

外柏叁布道者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值