8. go语言从零实现以太坊响应端 - 查询区块链账户余额

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(&param); 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

查询余额

欢迎点赞、收藏、评论

相关推荐
名字还没想好☜4 小时前
Go 的 time.After 在 select 循环里内存泄漏:定时器堆积原理与 timer.Reset 正确姿势
java·数据库·golang·go·goroutine
ttwuai6 小时前
GoFrame 后台日志清空失败:无 WHERE 删除为什么被拦住
前端·golang
进击的程序猿~7 小时前
Go 并发底层原理面试学习指南
开发语言·面试·golang
不在逃避q7 小时前
Golang笔记之Redis
redis·笔记·golang
Web3_Daisy12 小时前
如何在Robinhood Chain创建 Uniswap V3 流动性池
大数据·人工智能·web3·区块链
同花顺期货通12 小时前
期货交割月持仓规则全解析:2026年个人交易者合规指南与展期策略
区块链
潜龙952714 小时前
Web3.0新测试方案
web3·区块链·新测试方案
geovindu14 小时前
go:loghelper
开发语言·后端·golang
呐抹倾14 小时前
go学习笔记:panic是什么含义
笔记·学习·golang
想你依然心痛14 小时前
HarmonyOS 5.0智慧农业开发实战:构建分布式农业物联网与区块链农产品溯源系统
人工智能·分布式·物联网·区块链·智慧农业·harmonyos·开发实战