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

查询余额

欢迎点赞、收藏、评论

相关推荐
TechubNews2 小时前
当跨链协议开始将业务从「搭桥」拓展至「swap」
区块链
oMcLin2 小时前
如何在 SUSE Linux Enterprise Server 15 上通过配置 Nginx 与 PHP‑FPM 提升大流量电商平台的服务器响应能力
centos·去中心化·区块链
Mr -老鬼3 小时前
Java、Go、Rust高并发时代“称雄”之战:场景适配与生态博弈
java·golang·rust
oMcLin3 小时前
如何在 CentOS 7.9 上部署基于区块链的数字资产交易平台,确保交易透明度与去中心化安全性
centos·去中心化·区块链
源代码•宸4 小时前
Golang原理剖析(map)
经验分享·后端·算法·golang·哈希算法·散列表·map
MicroTech20254 小时前
后量子密码算法集成:微算法科技(NASDAQ: MLGO)构建区块链安全防护的量子盾牌
科技·安全·区块链
老蒋每日coding5 小时前
驾驭并发之力:Go语言构建高可用微服务完全指南
开发语言·微服务·golang
链科天下5 小时前
赵长鹏投资去中心化交易平台,想要打造“链上币安”?
区块链
老蒋每日coding5 小时前
Solidity入门(1)- Hardhat框架
区块链