go语言从零实现以太坊响应端 - 查询区块链账户余额
- [1. 环境配置和合约代码](#1. 环境配置和合约代码)
- [2. 编写调试代码](#2. 编写调试代码)
-
- [2.1 gin web框架](#2.1 gin web框架)
- [2.2 核心业务](#2.2 核心业务)
- [2.3 工具类](#2.3 工具类)
- [2.4 主函数](#2.4 主函数)
- [3. 测试](#3. 测试)
1. 环境配置和合约代码
参考文章12. Hardhat编写、编译、部署、测试Solidity ERC20合约 - 进阶篇 - Metamask导入代币,转账ETH,转账代币
GoLand 2025.2.4版本
go 1.25.4
2. 编写调试代码
可连接hardhat node本地网络和sepolia测试网络
为了突出业务逻辑,省略了错误处理。
2.1 gin web框架
因为请求端通过http post发送JSONRPC,所以响应端要提供http服务,选择了主流的gin web框架。
go
package domain
// RPCRequest JSON-RPC 请求结构体
type RPCRequest struct {
Method string `json:"method"`
Params []interface{} `json:"params,omitempty"`
ID int `json:"id"`
JSONRPC string `json:"jsonrpc"`
}
// RPCResponse JSON-RPC 响应结构体
type RPCResponse struct {
Method string `json:"method"`
ID int `json:"id"`
Result string `json:"result"`
}
url为http://127.0.0.1:8080,路由到BaseAPI方法,BaseAPI输入JSONRPC请求,返回JSONRPC响应。gin框架将http post的body中的JSONRPC请求数据反序列化为domain.RPCRequest对象。http响应装饰器将domain.RPCResponse序列化为json字符串,返回到请求端。
go
package router
import (
"server/domain"
"server/domain/decorator"
"server/utils"
"github.com/gin-gonic/gin"
"server/ethereum.server.blockchain/controller"
)
// SetRouter 设置路由。
func SetRouter(r *gin.Engine) {
group := r.Group("")
{
// url为http://127.0.0.1:8080,路由到BaseAPI方法
group.POST("", decorator.WithJSONBinding(BaseAPI))
}
}
// BaseAPI Web API 输入JSONRPC请求,返回JSONRPC响应。
// gin框架将http post的body中的JSONRPC请求数据反序列化为domain.RPCRequest对象。以太坊JSONRPC返回数据为16进制字符串
func BaseAPI(request domain.RPCRequest) domain.RPCResponse {
blockChaninReadController := controller.NewBlockChainReadController()
result := ""
switch request.Method {
// 查询区块链ID
case "eth_chainId":
result = utils.IntToHexStr(blockChaninReadController.EthChainId())
// 查询账户余额
case "eth_getBalance":
result = utils.BigIntToHexStr(blockChaninReadController.EthGetBalance(request.Params[0].(string)))
}
return domain.RPCResponse{
ID: request.ID,
Method: request.Method,
Result: result,
}
}
http响应装饰器
go
package decorator
import (
"net/http"
"github.com/gin-gonic/gin"
)
type Response struct {
Code int
Message string
Data interface{}
}
// WithJSONBinding 绑定装饰器
func WithJSONBinding[T any, U any](handler func(T) U) gin.HandlerFunc {
return func(c *gin.Context) {
var param T
if err := c.ShouldBindJSON(¶m); err != nil {
c.JSON(http.StatusBadRequest, Response{http.StatusBadRequest, err.Error(), nil})
return
}
c.JSON(http.StatusOK, Response{http.StatusOK, "success", handler(param)})
}
}
2.2 核心业务
对外暴露层-controller
go
package controller
import (
"math/big"
"server/ethereum.server.blockchain/service"
)
type BlockChainReadController struct {
service *service.BlockChainReadService
}
// NewBlockChainReadController 创建BlockChainReadController对象
func NewBlockChainReadController() *BlockChainReadController {
return &BlockChainReadController{service.NewBlockChainReadService()}
}
// EthChainId 查询区块链ID
func (this *BlockChainReadController) EthChainId() uint64 {
return this.service.EthChainId()
}
// EthGetBalance 查询账户余额
func (this *BlockChainReadController) EthGetBalance(address string) *big.Int {
return this.service.EthGetBalance(address)
}
核心业务逻辑层-service
go
package domain
import "math/big"
type EtheAccount struct {
// 账户地址
Address []byte
// 账户nonce
Nonce uint64
// 账户余额
Balance *big.Int
}
基类
go
package service
import (
"server/domain"
)
type BaseService struct {
// 账户信息。账户地址为key,账户信息为value
etheAccounts map[string]*domain.EtheAccount
}
实现类
go
package service
import "math/big"
type BlockChainReadService struct {
BaseService
chainID string
}
// NewBlockChainReadService 创建对象
func NewBlockChainReadService() *BlockChainReadService {
return &BlockChainReadService{}
}
// EthChainId 查询区块链ID
func (this *BlockChainReadService) EthChainId() uint64 {
return 11155111
}
// EthGetBalance 获取账户余额
func (this *BlockChainReadService) EthGetBalance(address string) *big.Int {
account := this.etheAccounts[address]
if account != nil {
return account.Balance
}
return big.NewInt(0)
}
2.3 工具类
go
package utils
import (
"fmt"
"math/big"
)
func IntToHexStr(num uint64) string {
return fmt.Sprintf("%#x", num)
}
func BigIntToHexStr(num *big.Int) string {
hexStr := "0x" + fmt.Sprintf("0x%x", num)
return hexStr
}
2.4 主函数
go
package main
import (
"server/utils/router"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
router.SetRouter(r)
r.Run("127.0.0.1:8080")
}
3. 测试
查询区块链ID

查询余额

欢迎点赞、收藏、评论