go语言从零实现以太坊客户端-查询区块链账户余额
- [1. 环境配置和合约代码](#1. 环境配置和合约代码)
- [2. 编写调试代码](#2. 编写调试代码)
-
- [2.1 基类,用于初始化常量](#2.1 基类,用于初始化常量)
- [2.2 核心业务类](#2.2 核心业务类)
- [2.3 JSON-RPC库](#2.3 JSON-RPC库)
- [2.4 装饰器](#2.4 装饰器)
- [2.5 工具类](#2.5 工具类)
- [2.6 主函数](#2.6 主函数)
- [3. 测试](#3. 测试)
-
- [3.1 hardhat node节点](#3.1 hardhat node节点)
- [3.2 sepolia节点](#3.2 sepolia节点)
1. 环境配置和合约代码
参考文章12. Hardhat编写、编译、部署、测试Solidity ERC20合约 - 进阶篇 - Metamask导入代币,转账ETH,转账代币
GoLand 2025.2.4版本
go 1.25.4
2. 编写调试代码
可连接hardhat node本地网络和sepolia测试网络
为了突出业务逻辑,省略了错误处理。
2.1 基类,用于初始化常量
后面文章中的类均继承BaseService类
clike
package service
import "client/utils/jsonrpc"
type BaseService struct {
url string
contractAddr string
from string
to string
privateKey string
chainID uint64
}
func (this *BaseService) Init() {
this.url = "http://localhost:8545"
this.contractAddr = "0x5FbDB2315678afecb367f032d93F642f64180aa3"
// hardhat 默认账户地址1
this.from = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"
// hardhat 默认账户地址2
this.to = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
this.privateKey = 你自己的私钥
this.chainID = uint64(1337)
//this.url = "https://ethereum-sepolia-rpc.publicnode.com"
//this.contractAddr = "0x451Dc02Cee616361815253C858Df0a3028c42901"
//// sepolia 账户地址1
//this.from = "0xc312c07abEb8246510412a7ce87A295E0ceC5D48"
//// sepolia 账户地址1
//this.to = "0xE78Ff27498c9a6Fd8BC3ff8170Ecf9a13ECBE49e"
//this.privateKey = 你自己的私钥
//this.chainID = uint64(11155111)
//this.url = "https://webhook.site/fc1b1d2d-7dcd-4a2a-b653-16d8f2b9de0e"
jsonrpc.InitJsonRPCClient(this.url)
}
2.2 核心业务类
继承基类。查询区块链ID和账户余额
//go:decor decorator.LogJsonRPC是装饰器,用来做返回值类型转换。以太坊JSON-RPC返回的数据是十六进制字符串,要转换为对应的类型
clike
package service
import (
_ "client/domain/decorator"
"client/utils/jsonrpc"
_ "github.com/dengsgo/go-decorator/decor"
)
//go:decor decorator.LogJsonRPC
type BlockChainRead struct {
BaseService
}
func (this *BlockChainRead) GetChainID() interface{} {
return jsonrpc.SendJsonRPC("eth_chainId")
}
// GetBalance
// DATA, 20 Bytes - address to check for balance.
// QUANTITY|TAG - integer block number, or the string "latest", "earliest", "pending", "safe", or "finalized", see the block parameter
// params: ["0x407d73d8a49eeb85d32cf465507dd71d507100c1", "latest"]
func (this *BlockChainRead) GetBalance() interface{} {
return jsonrpc.SendJsonRPC("eth_getBalance", this.from, "latest")
}
2.3 JSON-RPC库
使用JSON-RPC库github.com/ybbus/jsonrpc/v3,组装
clike
{
jsonrpc: '2.0',
method: "eth_getBalance"
params: [this.from, "latest"]
id: 1
}
clike
package jsonrpc
import (
_ "client/domain/decorator"
"context"
_ "github.com/dengsgo/go-decorator/decor"
"github.com/ybbus/jsonrpc/v3"
)
var JsonRPCClient jsonrpc.RPCClient
func InitJsonRPCClient(url string) {
JsonRPCClient = jsonrpc.NewClient(url)
}
func SendJsonRPC(funcName string, params ...interface{}) interface{} {
var rsp interface{}
err := JsonRPCClient.CallFor(context.Background(), &rsp, funcName, params)
if err != nil {
panic(err)
}
return rsp
}
2.4 装饰器
以太坊的JSON-RPC返回的值是十六进制字符串,需要转换为对应的类型。为了分离非业务代码和业务代码,架构层面分层清晰,这里统一使用装饰器做返回值转换,这里选择了"github.com/dengsgo/go-decorator/decor"开源框架,只需要在被装饰的类上加//go:decor decorator.LogJsonRPC即可。
clike
package decorator
import (
"client/utils"
"github.com/dengsgo/go-decorator/decor"
)
func LogJsonRPC(ctx *decor.Context) {
if ctx.Func != nil {
ctx.Func()
if ctx.TargetOut == nil || len(ctx.TargetOut) == 0 {
return
}
ctx.TargetOut[0] = utils.HexStrToInt(ctx.TargetOut[0].(string))
}
}
2.5 工具类
工具类
clike
package utils
import (
"math/big"
"strings"
)
func HexStrToInt(hexStr string) *big.Int {
data, _ := new(big.Int).SetString(strings.TrimPrefix(hexStr, "0x"), 16)
return data
}
2.6 主函数
clike
package main
import (
"fmt"
"client/ethereum.client.blockchain/service"
)
func main() {
blockchainRead()
}
func blockchainRead() {
blockChainRead := service.BlockChainRead{}
blockChainRead.Init()
id := blockChainRead.GetChainID()
balance := blockChainRead.GetBalance()
fmt.Println(id, balance)
}
3. 测试
3.1 hardhat node节点

3.2 sepolia节点
