美文网首页收藏
Cosmos 使用 Ignite-Cli 快速开发 NameSe

Cosmos 使用 Ignite-Cli 快速开发 NameSe

作者: VictorXSS | 来源:发表于2022-11-16 17:46 被阅读0次

    概述

    这篇文章主要讲述使用CosmosIgnite-Cli工具快速开发NameService应用。NameService的主要功能是用户可以购买域名,给域名设置可以解析的地址或则值,域名拥有者可以删除域名。

    环境安装

    1. 我们使用 Docker 来部署环境,首先编写 DockerFile 镜像文件,命名DockerFile-ubuntu
    FROM --platform=linux ubuntu:22.04
    ARG BUILDARCH
    
    # Change your versions here
    ENV GO_VERSION=1.18.3
    ENV IGNITE_VERSION=0.22.1
    ENV NODE_VERSION=18.x
    
    ENV LOCAL=/usr/local
    ENV GOROOT=$LOCAL/go
    ENV HOME=/root
    ENV GOPATH=$HOME/go
    ENV PATH=$GOROOT/bin:$GOPATH/bin:$PATH
    
    RUN mkdir -p $GOPATH/bin
    
    ENV PACKAGES curl gcc jq
    RUN apt-get update
    RUN apt-get install -y $PACKAGES
    
    # Install Go
    RUN curl -L https://go.dev/dl/go${GO_VERSION}.linux-$BUILDARCH.tar.gz | tar -C $LOCAL -xzf -
    
    # Install Ignite
    RUN curl -L https://get.ignite.com/cli@v${IGNITE_VERSION}! | bash
    
    # Install Node
    RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION} | bash -
    RUN apt-get install -y nodejs
    
    EXPOSE 1317 3000 4500 5000 26657
    
    WORKDIR /nameservice
    
    1. 创建镜像
    docker build -f DockerFile-ubuntu . -t ns_i
    
    1. 创建 Container
    docker create --name ns -i -v $(pwd):/nameservice -w /nameservice -p 1317:1317 -p 4500:4500 -p 5000:5000 -p 26657:26657 ns_i
    
    1. 启动容器
    docker start ns
    
    1. 检查环境
    docker exec -it ns ignite version
    

    显示如下内容,则表示环境安装成功。

    Ignite CLI version:     v0.22.1
    

    如果环境安装有问题,可以私信我帮你看看!

    创建项目

    docker exec -it ns ignite scaffold chain nameservice --no-module
    

    这个命令会创建一个nameservice目录,已经实现了基于Cosmos SDK的区块链功能。
    然后我们把代码移动到当前的工作目录

    mv nameservice/* ./
    rm -rf nameservice
    

    创建Module

    docker exec -it ns ignite scaffold module nameservice --dep bank
    

    --dep bank表示该模块依赖bank模块

    创建Message

    根据我们的业务我们需要创建 3 个Message

    • BuyName(Name, Bid) // 购买域名
    • SetName(Name, Value) // 给域名设置值
    • DeleteName(Name) // 删除域名
      我们需要执行以下命令创建这些Message:
    docker exec -it ns ignite scaffold message buy-name name bid
    

    buy-name是方法名,(name, bid)是参数

    docker exec -it ns ignite scaffold message set-name name value
    

    set-name是方法名,(name, value)是参数

    docker exec -it ns ignite scaffold message delete-name name
    

    delete-name是方法名,(name)是参数

    创建Types

    现在我们需要创建一个储存的数据结构来记录当前域名的归属关系,我们创建一个Whois的结构

    docker exec -it ns ignite scaffold map whois name value price owner --no-message
    
    • whois是 type
    • name是域名
    • value是域名映射的值
    • price是当前域名的价格
    • owner是当前域名的拥有者
    • --no-message表示不需要创建message

    实现业务代码

    1. 声明bank下我们需要用到的方法,编辑x/nameservice/types/expected_keepers.go
    // x/nameservice/types/expected_keepers.go
    
    package types
    
    import (
        sdk "github.com/cosmos/cosmos-sdk/types"
    )
    
    type BankKeeper interface {
        SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error // 需要添加的方法
        SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error // 需要添加的方法
    }
    
    1. 编辑x/nameservice/keeper/msg_server_buy_name.go文件,实现购买逻辑
    // x/nameservice/keeper/msg_server_buy_name.go
    
    package keeper
    
    import (
        "context"
    
        sdk "github.com/cosmos/cosmos-sdk/types"
        sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    
        "nameservice/x/nameservice/types"
    )
    
    func (k msgServer) BuyName(goCtx context.Context, msg *types.MsgBuyName) (*types.MsgBuyNameResponse, error) {
        ctx := sdk.UnwrapSDKContext(goCtx)
    
        // 从store中获取域名数据
        whois, isFound := k.GetWhois(ctx, msg.Name)
    
        // 设置域名购买的初始最低价
        minPrice := sdk.Coins{sdk.NewInt64Coin("token", 10)}
    
        // 把价格转换成代币
        price, _ := sdk.ParseCoinsNormalized(whois.Price)
        bid, _ := sdk.ParseCoinsNormalized(msg.Bid)
    
        // 转换地址
        owner, _ := sdk.AccAddressFromBech32(whois.Owner)
        buyer, _ := sdk.AccAddressFromBech32(msg.Creator)
    
        // 如果当前域名数据已经存在
        if isFound {
            // 如果当前价格大于竞拍价格
            if price.IsAllGT(bid) {
                // 抛出错误
                return nil, sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, "Bid is not high enough")
            }
    
            // 如果当前价格小于竞拍价格,把购买者的代币转给域名拥有者
            err := k.bankKeeper.SendCoins(ctx, buyer, owner, bid)
            if err != nil {
                return nil, err
            }
        } else { // 如果域名不存在
            // 如果域名购买最低价大于竞拍价格
            if minPrice.IsAllGT(bid) {
                // 抛出错误
                return nil, sdkerrors.Wrap(sdkerrors.ErrInsufficientFunds, "Bid is less than min amount")
            }
    
            // 如果当前价格小于竞拍价格,把购买者的代币转到模块地址
            err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, buyer, types.ModuleName, bid)
            if err != nil {
                return nil, err
            }
        }
    
        // 更新`whois`的数据
        newWhois := types.Whois{
            Index: msg.Name,
            Name:  msg.Name,
            Value: whois.Value,
            Price: bid.String(),
            Owner: buyer.String(),
        }
    
        // 储存到store
        k.SetWhois(ctx, newWhois)
        return &types.MsgBuyNameResponse{}, nil
    }
    
    1. 编辑x/nameservice/keeper/msg_server_set_name.go,实现设置域名映射值的逻辑
    // x/nameservice/keeper/msg_server_set_name.go
    
    package keeper
    
    import (
        "context"
    
        sdk "github.com/cosmos/cosmos-sdk/types"
        sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    
        "nameservice/x/nameservice/types"
    )
    
    func (k msgServer) SetName(goCtx context.Context, msg *types.MsgSetName) (*types.MsgSetNameResponse, error) {
        ctx := sdk.UnwrapSDKContext(goCtx)
    
        // 从store中获取域名数据
        whois, _ := k.GetWhois(ctx, msg.Name)
    
        // 如果方法调用者不是域名拥有者,则报错
        if !(msg.Creator == whois.Owner) {
            return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Incorrect Owner")
        }
    
        // 更新whois的记录,设置值
        newWhois := types.Whois{
            Index: msg.Name,
            Name:  msg.Name,
            Value: msg.Value,
            Owner: whois.Owner,
            Price: whois.Price,
        }
    
        // 储存到store
        k.SetWhois(ctx, newWhois)
        return &types.MsgSetNameResponse{}, nil
    }
    
    1. 编辑x/nameservice/keeper/msg_server_delete_name.go,实现域名删除逻辑
    // x/nameservice/keeper/msg_server_delete_name.go
    
    package keeper
    
    import (
        "context"
    
        sdk "github.com/cosmos/cosmos-sdk/types"
        sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    
        "nameservice/x/nameservice/types"
    )
    
    func (k msgServer) DeleteName(goCtx context.Context, msg *types.MsgDeleteName) (*types.MsgDeleteNameResponse, error) {
        ctx := sdk.UnwrapSDKContext(goCtx)
    
        // 从store中获取域名数据
        whois, isFound := k.GetWhois(ctx, msg.Name)
    
        // 如果找不到域名,则报错
        if !isFound {
            return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Name doesn't exist")
        }
    
        // 如果方法调用者不是域名拥有者,则报错
        if !(whois.Owner == msg.Creator) {
            return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "Incorrect Owner")
        }
    
        // 将域名从store中删除
        k.RemoveWhois(ctx, msg.Name)
        return &types.MsgDeleteNameResponse{}, nil
    }
    

    测试

    1. 启动节点
    docker exec -it ns ignite chain serve -r
    

    -r表示重置节点数据 2. 测试购买域名

    docker exec -it ns nameserviced tx nameservice buy-name foo 20token --from alice
    
    1. 查询域名数据
    docker exec -it ns nameserviced q nameservice list-whois
    
    1. 测试设置域名值
    docker exec -it ns nameserviced tx nameservice set-name foo bar --from alice
    
    1. 测试删除域名
    docker exec -it ns nameserviced tx nameservice delete-name foo --from alice
    

    总结

    这篇文章只是告诉大家如何使用Ignite-CLI更加快速的开发Cosmos项目,如果想更深入的理解相关代码,请参考以下链接
    官方文档:https://docs.ignite.com/guide/nameservice
    登链社区文档:https://learnblockchain.cn/docs/cosmos/tutorial/#%E5%BC%80%E5%A7%8B

    如果你不会使用 Docker,也可以自己安装本地环境,参考链接:https://tutorials.cosmos.network/hands-on-exercise/1-ignite-cli/1-ignitecli.html

    我是 Victor,Web3 爱好者!希望帮助更多人进入 Web3 的世界!

    如果有任何问题,请私信我!

    相关文章

      网友评论

        本文标题:Cosmos 使用 Ignite-Cli 快速开发 NameSe

        本文链接:https://www.haomeiwen.com/subject/gfzyxdtx.html