10_erc20

command
v0.0.0-...-6e38dd8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 12, 2023 License: MIT Imports: 5 Imported by: 0

README

同质化代币ERC20

这一节终于来到了同质化代币ERC20,有些场合也会被叫做Token,即令牌。

关于ERC20代币标准的资料已经非常多,这里不展开了。这一节主要看一下Go语言如何和ERC20代币交互。 我们先从订阅转账消息开始。

Go和以太坊智能合约交互,是使用了以太坊的JSON-RPC接口,即把所有读取写入请求转换成RPC请求,发送给以太坊节点,并等待回应。这和之前转账是完全一致的,只不过交互的地址从EOA变成了合约而已。

但是,合约交互不比简单转账,它是有参数的,而且参数的编码也要严格遵守规范。如果不借助工具,这个编码过程是非常繁琐的。幸运的是,有工具。

go-ethereum自带的abigen可以根据ABI文件,自动生成对应的Go文件。有了这些文件,我们不用费功夫编解码了,可以直接使用所有函数,跟本地函数类似。

获得ABI文件的方法有很多,可以从etherscan网站拷贝,可以从源码编译等。我随便举例其中的一种。

我先从OpenZeppelin库https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.1/contracts/token/ERC20/IERC20.sol下载接口文件,然后放到Remix里编译,拷贝出ABI文件。

假设保存的ABI文件名是IERC20.json。运行命令

abigen --abi IERC20.json --type ERC20 --pkg er
c20 --out erc20.go

可以得到Go文件erc20.go,里边自动生成的类名是ERC20

有了这个文件,我们可以找一个符合ERC20标准的测试网代币试一试了。我选中了sepolia网络的LINK代币,因为这个代币的水龙头容易找 https://faucets.chain.link/sepolia。它的合约地址是0x779877A7B0D9E8603169DdbD7836e478b4624789

使用之前的*ethclient.Client,新建一个ERC20对象

address := common.HexToAddress("0x779877A7B0D9E8603169DdbD7836e478b4624789")
link, err := erc20.NewERC20(address, ec)

查询某个账户持有的代币余额

account := common.HexToAddress("0xAc25D7217FCCff38Ba52d3a7F453506522428713")
balance, err := link.BalanceOf(nil, account)

完整代码

package main

import (
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/ethclient"
	"github.com/xingyongtao/ethereum-development-with-go/10_erc20/erc20"
	"log"
	"os"
)

func main() {
	apiKey := os.Getenv("INFURA_API_KEY")
	url := "https://sepolia.infura.io/v3/" + apiKey
	ec, err := ethclient.Dial(url)
	if err != nil {
		log.Fatalf("could not connect to Infura with ethclient: %s", err)
	}

	address := common.HexToAddress("0x779877A7B0D9E8603169DdbD7836e478b4624789")
	link, err := erc20.NewERC20(address, ec)
	if err != nil {
		log.Fatalf("new erc20 error: %s", err)
	}
	account := common.HexToAddress("0xAc25D7217FCCff38Ba52d3a7F453506522428713")
	balance, err := link.BalanceOf(nil, account)
	if err != nil {
		log.Fatalf("get balance error: %s", err)
	}
	log.Printf("account %s has balance %s", account, balance)
}

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL