Nameservice 模块的 CLI
Cosmos SDK使用cobra
库进行CLI交互。该库使每个模块都可以轻松地显示自己的操作命令。要开始定义用户与模块的CLI交互,请创建以下文件:
./x/nameservice/client/cli/query.go
./x/nameservice/client/cli/tx.go
./x/nameservice/client/module_client.go
## Queries
在query.go
文件中为你模块的每个Query
(resolve
和whois
)定义cobra.Command
:
package cli
import (
"fmt"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/sdk-application-tutorial/x/nameservice"
"github.com/spf13/cobra"
)
// GetCmdResolveName queries information about a name
func GetCmdResolveName(queryRoute string, cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "resolve [name]",
Short: "resolve name",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
name := args[0]
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/resolve/%s", queryRoute, name), nil)
if err != nil {
fmt.Printf("could not resolve name - %s \n", string(name))
return nil
}
var out nameservice.QueryResResolve
cdc.MustUnmarshalJSON(res, &out)
return cliCtx.PrintOutput(out)
},
}
}
// GetCmdWhois queries information about a domain
func GetCmdWhois(queryRoute string, cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "whois [name]",
Short: "Query whois info of name",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
name := args[0]
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/whois/%s", queryRoute, name), nil)
if err != nil {
fmt.Printf("could not resolve whois - %s \n", string(name))
return nil
}
var out nameservice.Whois
cdc.MustUnmarshalJSON(res, &out)
return cliCtx.PrintOutput(out)
},
}
}
// GetCmdNames queries a list of all names
func GetCmdNames(queryRoute string, cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "names",
Short: "names",
// Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc)
res, err := cliCtx.QueryWithData(fmt.Sprintf("custom/%s/names", queryRoute), nil)
if err != nil {
fmt.Printf("could not get query names\n")
return nil
}
var out nameservice.QueryResNames
cdc.MustUnmarshalJSON(res, &out)
return cliCtx.PrintOutput(out)
},
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
注意上述代码中:
CLI 引入了一个新的
context
:CLIContext
。它包含有关CLI交互所需的用户输入和应用程序配置的数据。cliCtx.QueryWithData()
函数所需的path
直接从你的查询路径中映射。- 路径的第一部分用于区分 SDK 应用程序可能的querier类型:
custom
用于Querier
- 第二部分(
nameservice
)是将查询路由到的模块的名称。 - 最后是要调用模块中的特定的querier。
- 在这个例子中,第四部分是查询。这是因为查询参数是一个简单的字符串。要启用更复杂的查询输入,你需要使用
.QueryWithData()
函数的第二个参数来传入data
。有关此示例,请参阅 Staking 模块中的 queriers。
- 路径的第一部分用于区分 SDK 应用程序可能的querier类型:
Transaction
现在已经定义了查询交互,是时候继续在tx.go
中的交易生成了:
你的应用程序需要导入你刚编写的代码。这里导入路径设置为此存储库(github.com/cosmos/sdk-application-tutorial/x/nameservice)。如果您是在自己的仓库中进行的前面的操作,则需要更改导入路径(github.com/{.Username}/{.Project.Repo}/x/nameservice)。
package cli
import (
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/utils"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/sdk-application-tutorial/x/nameservice"
sdk "github.com/cosmos/cosmos-sdk/types"
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
)
// GetCmdBuyName is the CLI command for sending a BuyName transaction
func GetCmdBuyName(cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "buy-name [name] [amount]",
Short: "bid for existing name or claim new name",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc).WithAccountDecoder(cdc)
txBldr := authtxb.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
if err := cliCtx.EnsureAccountExists(); err != nil {
return err
}
coins, err := sdk.ParseCoins(args[1])
if err != nil {
return err
}
msg := nameservice.NewMsgBuyName(args[0], coins, cliCtx.GetFromAddress())
err = msg.ValidateBasic()
if err != nil {
return err
}
cliCtx.PrintResponse = true
return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}, false)
},
}
}
// GetCmdSetName is the CLI command for sending a SetName transaction
func GetCmdSetName(cdc *codec.Codec) *cobra.Command {
return &cobra.Command{
Use: "set-name [name] [value]",
Short: "set the value associated with a name that you own",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
cliCtx := context.NewCLIContext().WithCodec(cdc).WithAccountDecoder(cdc)
txBldr := authtxb.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc))
if err := cliCtx.EnsureAccountExists(); err != nil {
return err
}
msg := nameservice.NewMsgSetName(args[0], args[1], cliCtx.GetFromAddress())
err := msg.ValidateBasic()
if err != nil {
return err
}
cliCtx.PrintResponse = true
return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg}, false)
},
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
注意在上述代码中:
- 使用了
authcmd
包。查看文档了解更多使用信息。它提供对CLI控制的帐户的访问权限,并便于签名。
Module Client
导出此功能的最后一部分称为ModuleClient
,在./x/nameservice/client/module_client.go
文件中实现。Module Client 为模块提供了导出客户端功能的标准方法。
注意:你的应用程序需要导入你刚编写的代码。这里导入路径设置为此仓库(github.com/cosmos/sdk-application-tutorial/x/nameservice)。如果你是在自己项目中编写的,则需要更改导入路径成(github.com/{.Username}/ {.Project.Repo}/x/nameservice)。
package client
import (
"github.com/cosmos/cosmos-sdk/client"
nameservicecmd "github.com/cosmos/sdk-application-tutorial/x/nameservice/client/cli"
"github.com/spf13/cobra"
amino "github.com/tendermint/go-amino"
)
// ModuleClient exports all client functionality from this module
type ModuleClient struct {
storeKey string
cdc *amino.Codec
}
func NewModuleClient(storeKey string, cdc *amino.Codec) ModuleClient {
return ModuleClient{storeKey, cdc}
}
// GetQueryCmd returns the cli query commands for this module
func (mc ModuleClient) GetQueryCmd() *cobra.Command {
// Group nameservice queries under a subcommand
namesvcQueryCmd := &cobra.Command{
Use: "nameservice",
Short: "Querying commands for the nameservice module",
}
namesvcQueryCmd.AddCommand(client.GetCommands(
nameservicecmd.GetCmdResolveName(mc.storeKey, mc.cdc),
nameservicecmd.GetCmdWhois(mc.storeKey, mc.cdc),
)...)
return namesvcQueryCmd
}
// GetTxCmd returns the transaction commands for this module
func (mc ModuleClient) GetTxCmd() *cobra.Command {
namesvcTxCmd := &cobra.Command{
Use: "nameservice",
Short: "Nameservice transactions subcommands",
}
namesvcTxCmd.AddCommand(client.PostCommands(
nameservicecmd.GetCmdBuyName(mc.cdc),
nameservicecmd.GetCmdSetName(mc.cdc),
)...)
return namesvcTxCmd
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
上述代码要注意: