欢迎光临
我们一直在努力

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

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

  • 1. 环境配置和合约代码
  • 2. 编写调试代码
    • 2.1 gin web框架
    • 2.2 核心业务
    • 2.3 工具类
    • 2.4 主函数
  • 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框架。

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字符串,返回到请求端。

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响应装饰器

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

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

package domain

import "math/big"

type EtheAccount struct {
// 账户地址
Address []byte
// 账户nonce
Nonce uint64
// 账户余额
Balance *big.Int
}

基类

package service

import (
"server/domain"
)

type BaseService struct {
// 账户信息。账户地址为key,账户信息为value
etheAccounts map[string]*domain.EtheAccount
}

实现类

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 工具类

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 主函数

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 在这里插入图片描述 查询余额 在这里插入图片描述

欢迎点赞、收藏、评论

赞(0)
未经允许不得转载:171主机测评 » 8. go语言从零实现以太坊响应端 - 查询区块链账户余额
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址