From 10bd5a2cacdc28b440f1d1f32399042ddff6d80d Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:04:44 +0000 Subject: [PATCH] feat(x/nft): add autocli options for tx (backport #17825) (#17974) Co-authored-by: Julien Robert --- client/v2/go.mod | 4 +- client/v2/go.sum | 2 + simapp/go.mod | 2 +- simapp/go.sum | 4 +- tests/go.mod | 2 +- tests/go.sum | 4 +- x/nft/CHANGELOG.md | 6 + x/nft/client/cli/tx.go | 66 ---------- x/nft/client/cli/tx_test.go | 239 ------------------------------------ x/nft/go.mod | 2 +- x/nft/module/autocli.go | 13 ++ x/nft/module/module.go | 7 -- 12 files changed, 29 insertions(+), 322 deletions(-) delete mode 100644 x/nft/client/cli/tx.go delete mode 100644 x/nft/client/cli/tx_test.go diff --git a/client/v2/go.mod b/client/v2/go.mod index 33c2672c40..425bfaedb1 100644 --- a/client/v2/go.mod +++ b/client/v2/go.mod @@ -9,7 +9,7 @@ require ( cosmossdk.io/x/tx v0.10.0 github.com/cockroachdb/errors v1.11.1 github.com/cosmos/cosmos-proto v1.0.0-beta.3 - github.com/cosmos/cosmos-sdk v0.50.0-rc.1.0.20231005110808-059498db8691 + github.com/cosmos/cosmos-sdk v0.50.0-rc.1.0.20231005134150-8334eefaaf7c github.com/cosmos/gogoproto v1.4.11 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 @@ -152,5 +152,3 @@ require ( nhooyr.io/websocket v1.8.6 // indirect pgregory.net/rapid v1.1.0 // indirect ) - -replace github.com/cosmos/cosmos-sdk => ./../../ diff --git a/client/v2/go.sum b/client/v2/go.sum index 4da6106d53..14e383e178 100644 --- a/client/v2/go.sum +++ b/client/v2/go.sum @@ -178,6 +178,8 @@ github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0 github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U= github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o= github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I= +github.com/cosmos/cosmos-sdk v0.50.0-rc.1.0.20231005134150-8334eefaaf7c h1:JTUU/Tm8ELhwnWoONafMcqNxmE7e3KKbh0ifvTTbGjs= +github.com/cosmos/cosmos-sdk v0.50.0-rc.1.0.20231005134150-8334eefaaf7c/go.mod h1:JbgPLZrh+yX+4+n1CPJ/uL9HrhZw6QVg0q7cTq2Iwq0= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= diff --git a/simapp/go.mod b/simapp/go.mod index e7df042ff9..6d1a1042dd 100644 --- a/simapp/go.mod +++ b/simapp/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( cosmossdk.io/api v0.7.1 - cosmossdk.io/client/v2 v2.0.0-20231005120212-0062bf2e7141 + cosmossdk.io/client/v2 v2.0.0-20231005134150-8334eefaaf7c cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/core v0.11.0 cosmossdk.io/depinject v1.0.0-alpha.4 diff --git a/simapp/go.sum b/simapp/go.sum index 03422ebab6..3debcba8cd 100644 --- a/simapp/go.sum +++ b/simapp/go.sum @@ -189,8 +189,8 @@ cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1V cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= cosmossdk.io/api v0.7.1 h1:PNQ1xN8+/0hj/sSD0ANqjkgfXFys+bZ5L8Hg7uzoUTU= cosmossdk.io/api v0.7.1/go.mod h1:ure9edhcROIHsngavM6mBLilMGFnfjhV/AaYhEMUkdo= -cosmossdk.io/client/v2 v2.0.0-20231005120212-0062bf2e7141 h1:ovyUcvPX740eqC7bnGZpw4yn5GS2bNZ5jacRqiDwqU8= -cosmossdk.io/client/v2 v2.0.0-20231005120212-0062bf2e7141/go.mod h1:0ycdqzdjVeUdKqgBbaxqSsc1C18GJc3uEF+uphv/MPg= +cosmossdk.io/client/v2 v2.0.0-20231005134150-8334eefaaf7c h1:WlbeJazcWL5OAxSIay1DXQ52xUshtsuGmzny+3cYOyE= +cosmossdk.io/client/v2 v2.0.0-20231005134150-8334eefaaf7c/go.mod h1:0ycdqzdjVeUdKqgBbaxqSsc1C18GJc3uEF+uphv/MPg= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= diff --git a/tests/go.mod b/tests/go.mod index 883ab0ade3..9e1f2a32c0 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -37,7 +37,7 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.1 // indirect cloud.google.com/go/storage v1.30.1 // indirect - cosmossdk.io/client/v2 v2.0.0-20231005120212-0062bf2e7141 // indirect + cosmossdk.io/client/v2 v2.0.0-20231005134150-8334eefaaf7c // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/x/circuit v0.0.0-20230925151519-64e0e8980834 // indirect filippo.io/edwards25519 v1.0.0 // indirect diff --git a/tests/go.sum b/tests/go.sum index 36dd7c9b33..ed85182d18 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -189,8 +189,8 @@ cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1V cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= cosmossdk.io/api v0.7.1 h1:PNQ1xN8+/0hj/sSD0ANqjkgfXFys+bZ5L8Hg7uzoUTU= cosmossdk.io/api v0.7.1/go.mod h1:ure9edhcROIHsngavM6mBLilMGFnfjhV/AaYhEMUkdo= -cosmossdk.io/client/v2 v2.0.0-20231005120212-0062bf2e7141 h1:ovyUcvPX740eqC7bnGZpw4yn5GS2bNZ5jacRqiDwqU8= -cosmossdk.io/client/v2 v2.0.0-20231005120212-0062bf2e7141/go.mod h1:0ycdqzdjVeUdKqgBbaxqSsc1C18GJc3uEF+uphv/MPg= +cosmossdk.io/client/v2 v2.0.0-20231005134150-8334eefaaf7c h1:WlbeJazcWL5OAxSIay1DXQ52xUshtsuGmzny+3cYOyE= +cosmossdk.io/client/v2 v2.0.0-20231005134150-8334eefaaf7c/go.mod h1:0ycdqzdjVeUdKqgBbaxqSsc1C18GJc3uEF+uphv/MPg= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0= cosmossdk.io/core v0.11.0 h1:vtIafqUi+1ZNAE/oxLOQQ7Oek2n4S48SWLG8h/+wdbo= diff --git a/x/nft/CHANGELOG.md b/x/nft/CHANGELOG.md index e79fa1e440..3a5ca96892 100644 --- a/x/nft/CHANGELOG.md +++ b/x/nft/CHANGELOG.md @@ -28,3 +28,9 @@ Ref: https://keepachangelog.com/en/1.0.0/ --> # Changelog + +## [Unreleased] + +### Features + +* [#17825](https://github.com/cosmos/cosmos-sdk/pull/17825) Add AutoCLI Options. diff --git a/x/nft/client/cli/tx.go b/x/nft/client/cli/tx.go deleted file mode 100644 index 3e3645706b..0000000000 --- a/x/nft/client/cli/tx.go +++ /dev/null @@ -1,66 +0,0 @@ -package cli - -import ( - "fmt" - "strings" - - "github.com/spf13/cobra" - - "cosmossdk.io/x/nft" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/cosmos/cosmos-sdk/version" -) - -// GetTxCmd returns the transaction commands for this module -func GetTxCmd() *cobra.Command { - nftTxCmd := &cobra.Command{ - Use: nft.ModuleName, - Short: "nft transactions subcommands", - Long: "Provides the most common nft logic for upper-level applications, compatible with Ethereum's erc721 contract", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - nftTxCmd.AddCommand( - NewCmdSend(), - ) - - return nftTxCmd -} - -// NewCmdSend creates a CLI command for MsgSend. -func NewCmdSend() *cobra.Command { - cmd := &cobra.Command{ - Use: "send [class-id] [nft-id] [receiver] --from [sender]", - Args: cobra.ExactArgs(3), - Short: "transfer ownership of nft", - Long: strings.TrimSpace(fmt.Sprintf(` - $ %s tx %s send --from --chain-id `, version.AppName, nft.ModuleName), - ), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - - if args[0] == "" || args[1] == "" || args[2] == "" { - return fmt.Errorf("class-id, nft-id and receiver cannot be empty") - } - - msg := nft.MsgSend{ - ClassId: args[0], - Id: args[1], - Sender: clientCtx.GetFromAddress().String(), - Receiver: args[2], - } - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - return cmd -} diff --git a/x/nft/client/cli/tx_test.go b/x/nft/client/cli/tx_test.go deleted file mode 100644 index 4c9d2c3148..0000000000 --- a/x/nft/client/cli/tx_test.go +++ /dev/null @@ -1,239 +0,0 @@ -package cli_test - -import ( - "context" - "fmt" - "io" - "testing" - - abci "github.com/cometbft/cometbft/abci/types" - rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock" - "github.com/stretchr/testify/suite" - - "cosmossdk.io/core/address" - "cosmossdk.io/math" - "cosmossdk.io/x/nft" - "cosmossdk.io/x/nft/client/cli" - nftmodule "cosmossdk.io/x/nft/module" - nfttestutil "cosmossdk.io/x/nft/testutil" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - codecaddress "github.com/cosmos/cosmos-sdk/codec/address" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" - "github.com/cosmos/cosmos-sdk/testutil" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/cosmos/cosmos-sdk/testutil/network" - sdk "github.com/cosmos/cosmos-sdk/types" - testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil" -) - -const ( - OwnerName = "owner" - Owner = "cosmos1kznrznww4pd6gx0zwrpthjk68fdmqypjpkj5hp" - OwnerArmor = `-----BEGIN TENDERMINT PRIVATE KEY----- -salt: C3586B75587D2824187D2CDA22B6AFB6 -type: secp256k1 -kdf: bcrypt - -1+15OrCKgjnwym1zO3cjo/SGe3PPqAYChQ5wMHjdUbTZM7mWsH3/ueL6swgjzI3b -DDzEQAPXBQflzNW6wbne9IfT651zCSm+j1MWaGk= -=wEHs ------END TENDERMINT PRIVATE KEY-----` - - testClassID = "kitty" - testClassName = "Crypto Kitty" - testClassSymbol = "kitty" - testClassDescription = "Crypto Kitty" - testClassURI = "class uri" - testID = "kitty1" - testURI = "kitty uri" -) - -var ( - ExpClass = nft.Class{ - Id: testClassID, - Name: testClassName, - Symbol: testClassSymbol, - Description: testClassDescription, - Uri: testClassURI, - } - - ExpNFT = nft.NFT{ - ClassId: testClassID, - Id: testID, - Uri: testURI, - } -) - -type CLITestSuite struct { - suite.Suite - - kr keyring.Keyring - encCfg testutilmod.TestEncodingConfig - baseCtx client.Context - clientCtx client.Context - ctx context.Context - - owner sdk.AccAddress - - ac address.Codec -} - -func TestCLITestSuite(t *testing.T) { - suite.Run(t, new(CLITestSuite)) -} - -func (s *CLITestSuite) SetupSuite() { - s.encCfg = testutilmod.MakeTestEncodingConfig(nftmodule.AppModuleBasic{}) - s.kr = keyring.NewInMemory(s.encCfg.Codec) - s.baseCtx = client.Context{}. - WithKeyring(s.kr). - WithTxConfig(s.encCfg.TxConfig). - WithCodec(s.encCfg.Codec). - WithClient(clitestutil.MockCometRPC{Client: rpcclientmock.Client{}}). - WithAccountRetriever(client.MockAccountRetriever{}). - WithOutput(io.Discard). - WithChainID("test-chain") - - s.ctx = svrcmd.CreateExecuteContext(context.Background()) - ctxGen := func() client.Context { - bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{}) - c := clitestutil.NewMockCometRPC(abci.ResponseQuery{ - Value: bz, - }) - return s.baseCtx.WithClient(c) - } - s.clientCtx = ctxGen() - - cfg, err := network.DefaultConfigWithAppConfig(nfttestutil.AppConfig) - s.Require().NoError(err) - - genesisState := cfg.GenesisState - nftGenesis := nft.GenesisState{ - Classes: []*nft.Class{&ExpClass}, - Entries: []*nft.Entry{{ - Owner: Owner, - Nfts: []*nft.NFT{&ExpNFT}, - }}, - } - - nftDataBz, err := s.encCfg.Codec.MarshalJSON(&nftGenesis) - s.Require().NoError(err) - genesisState[nft.ModuleName] = nftDataBz - - s.ac = codecaddress.NewBech32Codec("cosmos") - - s.initAccount() -} - -func (s *CLITestSuite) TestCLITxSend() { - accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - - extraArgs := []string{ - fmt.Sprintf("--%s=%s", flags.FlagFrom, OwnerName), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), - } - - testCases := []struct { - name string - args []string - expectedCode uint32 - expectErr bool - expErrMsg string - }{ - { - "class id is empty", - []string{ - "", - testID, - accounts[0].Address.String(), - }, - 0, - true, - "class-id, nft-id and receiver cannot be empty", - }, - { - "nft id is empty", - []string{ - testClassID, - "", - accounts[0].Address.String(), - }, - 0, - true, - "class-id, nft-id and receiver cannot be empty", - }, - { - "empty receiver address", - []string{ - testClassID, - testID, - "", - }, - 0, - true, - "class-id, nft-id and receiver cannot be empty", - }, - { - "valid transaction", - []string{ - testClassID, - testID, - accounts[0].Address.String(), - }, - 0, - false, - "", - }, - } - - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - args := append(tc.args, extraArgs...) - cmd := cli.NewCmdSend() - cmd.SetContext(s.ctx) - cmd.SetArgs(args) - - s.Require().NoError(client.SetCmdClientContextHandler(s.clientCtx, cmd)) - - out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, args) - if tc.expectErr { - s.Require().Error(err) - s.Require().Contains(err.Error(), tc.expErrMsg) - } else { - var txResp sdk.TxResponse - s.Require().NoError(err) - s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } -} - -func (s *CLITestSuite) initAccount() { - ctx := s.clientCtx - err := ctx.Keyring.ImportPrivKey(OwnerName, OwnerArmor, "1234567890") - s.Require().NoError(err) - accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - - keyinfo, err := ctx.Keyring.Key(OwnerName) - s.Require().NoError(err) - - args := []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(10))).String()), - } - - s.owner, err = keyinfo.GetAddress() - s.Require().NoError(err) - - amount := sdk.NewCoins(sdk.NewCoin("stake", math.NewInt(200))) - _, err = clitestutil.MsgSendExec(ctx, accounts[0].Address, s.owner, amount, s.ac, args...) - s.Require().NoError(err) -} diff --git a/x/nft/go.mod b/x/nft/go.mod index b48eca5052..af1cdcb874 100644 --- a/x/nft/go.mod +++ b/x/nft/go.mod @@ -17,7 +17,6 @@ require ( github.com/golang/mock v1.6.0 github.com/golang/protobuf v1.5.3 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/spf13/cobra v1.7.0 github.com/stretchr/testify v1.8.4 google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e google.golang.org/grpc v1.58.1 @@ -123,6 +122,7 @@ require ( github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.1 // indirect + github.com/spf13/cobra v1.7.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.16.0 // indirect diff --git a/x/nft/module/autocli.go b/x/nft/module/autocli.go index f4d6ef360e..5a9d8289fc 100644 --- a/x/nft/module/autocli.go +++ b/x/nft/module/autocli.go @@ -83,6 +83,19 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { }, Tx: &autocliv1.ServiceCommandDescriptor{ Service: nftv1beta1.Msg_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Send", + Use: "send [class-id] [nft-id] [receiver] --from [sender]", + Short: "Transfer ownership of NFT", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "class_id"}, + {ProtoField: "id"}, + {ProtoField: "receiver"}, + }, + // Sender is the signer of the transaction and is automatically added as from flag by AutoCLI. + }, + }, }, } } diff --git a/x/nft/module/module.go b/x/nft/module/module.go index c1254756f7..2728032358 100644 --- a/x/nft/module/module.go +++ b/x/nft/module/module.go @@ -5,7 +5,6 @@ import ( "encoding/json" gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime" - "github.com/spf13/cobra" "google.golang.org/grpc" modulev1 "cosmossdk.io/api/cosmos/nft/module/v1" @@ -15,7 +14,6 @@ import ( "cosmossdk.io/depinject" "cosmossdk.io/errors" "cosmossdk.io/x/nft" - "cosmossdk.io/x/nft/client/cli" "cosmossdk.io/x/nft/keeper" "cosmossdk.io/x/nft/simulation" @@ -86,11 +84,6 @@ func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx sdkclient.Context, mux } } -// GetTxCmd returns the transaction commands for the nft module -func (AppModuleBasic) GetTxCmd() *cobra.Command { - return cli.GetTxCmd() -} - // AppModule implements the sdk.AppModule interface type AppModule struct { AppModuleBasic