热点、深度、趋势全掌握,尽在BTC区块圈

钱包对接 RPC 节点 – 搭建多链统一 RPC 节点支持

多链 RPC 应用

在钱包开发中,我们经常要使用到 rpc 节点的调用,但是每一个链的 rpc 接口又有着差异,我们必须去对每一个链进行适配,十分麻烦。而多链 RPC 应用这个项目将会拯救你。

多链 RPC 应用是一个轻量级高性能的 Go RPC 服务,通过聚合多链的 rpc 接口,提供统一的接口调用。

核心特性多链 rpc 应用的系统架构图

image.png

多链 rpc 应用的系统架构相对而言比较简单。我们的策略工厂和每一个对接的链实现上都实现了 25 个必须的接口,在调用的时候,通过一个策略工厂来为每一个用户请求分发到不同的链实现上。

例如:一个调用者需要调用以太坊上的根据hash获取区块的一个接口,调用者只需传入以太坊的字符串“ethereum”和对应的 hash 值,我们程序中即可进行按照 ethereum 这个标志进行分发策略到以太坊的 rpc 实现上去完成调用。对调用者而言,无须关心这次调用的细节。

搭建一个多链 rpc 应用的步骤

详细代码可见: chain-union-rpc 如果有用,麻烦 点个 ️ start 、fork

️ 1. 项目架构

├── bin               protobuf 命令管理       
├── chains            支持的链       
├── chaindispatcher   接口分发
├── common            通用工具库
├── config            配置代码
├── proto             grpc 生成的 protobuf代码
├── main.go           程序主入口
├── go.mod            依赖管理
├── config.yml        配置文件
├── Makefile          shell 命令管理
├── README.md         项目文档
├── DEVSTEPTS.md      项目开发步骤

2. 编写 proto 文件3. 搭建 grpc 框架

    /*注册拦截器*/
    grpcServer := grpc.NewServer(grpc.UnaryInterceptor(dispatcher.Interceptor))
    defer grpcServer.GracefulStop()

/*注册实现的接口路由*/
chainsunion.RegisterChainsUnionServiceServer(grpcServer, dispatcher)

    if err := grpcServer.Serve(listen); err != nil {
        log.Error("failed to serve", "port", conf.Server.Port, "err", err)
        panic(err)
    }

/*新建处理器*/
func New(conf *config.Config) (*ChainDispatcher, error) {
    dispatcher := &ChainDispatcher{
        registry: make(map[ChainType]chains.IChainAdaptor),
    }
    /*适配器工厂,根据key 按策略分发给不同 adaptor 实现*/
    chainAdaptorFactoryMap := map[string]func(conf *config.Config) (chains.IChainAdaptor, error){
        strings.ToLower(ethereum.ChainName): ethereum.NewChainAdaptor,
    }
    supportedChains := []string{
        strings.ToLower(ethereum.ChainName),
    }
    /*全部 new 出来放到工厂 map 中*/
    for _, c := range conf.Chains {
        chainName := strings.ToLower(c)
        if factory, ok := chainAdaptorFactoryMap[chainName]; ok {
            adaptor, err := factory(conf)
            if err != nil {
                log.Crit("Failed to create chain adaptor", "err", err)
            }
            dispatcher.registry[chainName] = adaptor
        } else {
            log.Error("Unsupported chain type", "chain", chainName, "supportedChains", supportedChains)
        }
    }
    return dispatcher, nil
}

4. 实现对接 rpc 节点和数据平台的 client

type EthClient interface {
    BlockHeaderByNumber(*big.Int) (*types.Header, error)
    BlockHeaderByHash(common.Hash) (*types.Header, error)
    BlockHeadersByRange(*big.Int, *big.Int, uint) ([]types.Header, error)
    BlockByNumber(*big.Int) (*RpcBlock, error)
    BlockByHash(common.Hash) (*RpcBlock, error)
    LatestSafeBlockHeader() (*types.Header, error)
    LatestFinalizedBlockHeader() (*types.Header, error)
    TxCountByAddress(common.Address) (hexutil.Uint64, error)
    SuggestGasPrice() (*big.Int, error)
    SuggestGasTipCap() (*big.Int, error)
    SendRawTransaction(rawTx string) (*common.Hash, error)
    TxByHash(common.Hash) (*types.Transaction, error)
    TxReceiptByHash(common.Hash) (*types.Receipt, error)
    StorageHash(common.Address, *big.Int) (common.Hash, error)
    EthGetCode(common.Address) (string, error)
    GetBalance(address common.Address) (*big.Int, error)
    FilterLogs(filterQuery ethereum.FilterQuery, chainId uint) (Logs, error)
    Close()
}

    1. 链支持
    2. 地址转换
    3. 地址校验
    4. 根据区块号获取区块
    5. 根据 hash 获取区块
    6. 根据 hash 获取区块头
    7. 根据区块号获取区块头
    8. 根据范围获取区块头
    9. 获取账号信息
    10. 获取手续费
    11. 发送交易
    12. 根据地址获取交易
    13. 根据交易 hash 获取交易
    14. 构建未签名交易
    15. 构建已签名交易
    16. 交易解码,解析成可读形式
    17. 校验已签名交易
    18. 获取额外数据
    19. 获取某个地址的 NFT 列表
    20. 获取 NFT 的集合
    21. 获取 NFT 的细节
    22. 获取 NFT 的持有者列表
    23. 获取 NFT 的交易历史
    24. 获取某个地址的 NFT 交易历史
    25 获取范围内区块

运行测试

make test

image.png

grpc页面测试

image.png

使用本文
0
共享
上一篇

Damn Vulnerable DeFi V4 解决方案 — #4. 侧门

下一篇

从旅行者到生态共建者:Coinsidings的Web3文旅投资价值解析

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

阅读下一页