github.com/Finschia/finschia-sdk@v0.48.1/x/collection/client/cli/tx.go (about)

     1  package cli
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/spf13/cobra"
     8  
     9  	"github.com/Finschia/finschia-sdk/client"
    10  	"github.com/Finschia/finschia-sdk/client/flags"
    11  	"github.com/Finschia/finschia-sdk/client/tx"
    12  	sdk "github.com/Finschia/finschia-sdk/types"
    13  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
    14  	"github.com/Finschia/finschia-sdk/version"
    15  	"github.com/Finschia/finschia-sdk/x/collection"
    16  )
    17  
    18  const (
    19  	// common flags for the entities
    20  	FlagName = "name"
    21  	FlagMeta = "meta"
    22  
    23  	// flag for contracts
    24  	FlagBaseImgURI = "base-img-uri"
    25  
    26  	// flag for fungible token classes
    27  	FlagDecimals = "decimals"
    28  	FlagMintable = "mintable"
    29  	FlagTo       = "to"
    30  	FlagSupply   = "supply"
    31  
    32  	DefaultDecimals = 8
    33  	DefaultSupply   = "0"
    34  )
    35  
    36  // NewTxCmd returns the transaction commands for this module
    37  func NewTxCmd() *cobra.Command {
    38  	txCmd := &cobra.Command{
    39  		Use:                        collection.ModuleName,
    40  		Short:                      fmt.Sprintf("%s transactions subcommands", collection.ModuleName),
    41  		DisableFlagParsing:         true,
    42  		SuggestionsMinimumDistance: 2,
    43  		RunE:                       client.ValidateCmd,
    44  	}
    45  
    46  	txCmd.AddCommand(
    47  		NewTxCmdSendFT(),
    48  		NewTxCmdOperatorSendFT(),
    49  		NewTxCmdSendNFT(),
    50  		NewTxCmdOperatorSendNFT(),
    51  		NewTxCmdCreateContract(),
    52  		NewTxCmdIssueFT(),
    53  		NewTxCmdIssueNFT(),
    54  		NewTxCmdMintFT(),
    55  		NewTxCmdMintNFT(),
    56  		NewTxCmdAttach(),
    57  		NewTxCmdDetach(),
    58  		NewTxCmdOperatorAttach(),
    59  		NewTxCmdOperatorDetach(),
    60  		NewTxCmdGrantPermission(),
    61  		NewTxCmdRevokePermission(),
    62  		NewTxCmdAuthorizeOperator(),
    63  		NewTxCmdRevokeOperator(),
    64  		NewTxCmdModify(),
    65  	)
    66  
    67  	return txCmd
    68  }
    69  
    70  func NewTxCmdSendFT() *cobra.Command {
    71  	cmd := &cobra.Command{
    72  		Use:   "send-ft [contract-id] [from] [to] [amount]",
    73  		Args:  cobra.ExactArgs(4),
    74  		Short: "send fungible tokens",
    75  		Long: strings.TrimSpace(fmt.Sprintf(`
    76  			$ %s tx %s send-ft [contract-id] [from] [to] [amount]`, version.AppName, collection.ModuleName),
    77  		),
    78  		RunE: func(cmd *cobra.Command, args []string) error {
    79  			from := args[1]
    80  			if err := cmd.Flags().Set(flags.FlagFrom, from); err != nil {
    81  				return err
    82  			}
    83  
    84  			clientCtx, err := client.GetClientTxContext(cmd)
    85  			if err != nil {
    86  				return err
    87  			}
    88  
    89  			amountStr := args[3]
    90  			amount, err := collection.ParseCoins(amountStr)
    91  			if err != nil {
    92  				return err
    93  			}
    94  
    95  			msg := &collection.MsgSendFT{
    96  				ContractId: args[0],
    97  				From:       from,
    98  				To:         args[2],
    99  				Amount:     amount,
   100  			}
   101  			if err := msg.ValidateBasic(); err != nil {
   102  				return err
   103  			}
   104  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
   105  		},
   106  	}
   107  
   108  	flags.AddTxFlagsToCmd(cmd)
   109  	return cmd
   110  }
   111  
   112  func NewTxCmdOperatorSendFT() *cobra.Command {
   113  	cmd := &cobra.Command{
   114  		Use:   "operator-send-ft [contract-id] [operator] [from] [to] [amount]",
   115  		Args:  cobra.ExactArgs(5),
   116  		Short: "send tokens by operator",
   117  		Long: strings.TrimSpace(fmt.Sprintf(`
   118  			$ %s tx %s operator-send-ft [contract-id] [operator] [from] [to] [amount]`, version.AppName, collection.ModuleName),
   119  		),
   120  		RunE: func(cmd *cobra.Command, args []string) error {
   121  			operator := args[1]
   122  			if err := cmd.Flags().Set(flags.FlagFrom, operator); err != nil {
   123  				return err
   124  			}
   125  
   126  			clientCtx, err := client.GetClientTxContext(cmd)
   127  			if err != nil {
   128  				return err
   129  			}
   130  
   131  			amountStr := args[4]
   132  			amount, err := collection.ParseCoins(amountStr)
   133  			if err != nil {
   134  				return err
   135  			}
   136  
   137  			msg := collection.MsgOperatorSendFT{
   138  				ContractId: args[0],
   139  				Operator:   operator,
   140  				From:       args[2],
   141  				To:         args[3],
   142  				Amount:     amount,
   143  			}
   144  			if err := msg.ValidateBasic(); err != nil {
   145  				return err
   146  			}
   147  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   148  		},
   149  	}
   150  
   151  	flags.AddTxFlagsToCmd(cmd)
   152  	return cmd
   153  }
   154  
   155  func NewTxCmdSendNFT() *cobra.Command {
   156  	cmd := &cobra.Command{
   157  		Use:   "send-nft [contract-id] [from] [to] [token-id]",
   158  		Args:  cobra.ExactArgs(4),
   159  		Short: "send non-fungible tokens",
   160  		Long: strings.TrimSpace(fmt.Sprintf(`
   161  			$ %s tx %s send-nft [contract-id] [from] [to] [token-id]`, version.AppName, collection.ModuleName),
   162  		),
   163  		RunE: func(cmd *cobra.Command, args []string) error {
   164  			from := args[1]
   165  			if err := cmd.Flags().Set(flags.FlagFrom, from); err != nil {
   166  				return err
   167  			}
   168  
   169  			clientCtx, err := client.GetClientTxContext(cmd)
   170  			if err != nil {
   171  				return err
   172  			}
   173  
   174  			msg := &collection.MsgSendNFT{
   175  				ContractId: args[0],
   176  				From:       from,
   177  				To:         args[2],
   178  				TokenIds:   []string{args[3]},
   179  			}
   180  			if err := msg.ValidateBasic(); err != nil {
   181  				return err
   182  			}
   183  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
   184  		},
   185  	}
   186  
   187  	flags.AddTxFlagsToCmd(cmd)
   188  	return cmd
   189  }
   190  
   191  func NewTxCmdOperatorSendNFT() *cobra.Command {
   192  	cmd := &cobra.Command{
   193  		Use:   "operator-send-nft [contract-id] [operator] [from] [to] [amount]",
   194  		Args:  cobra.ExactArgs(5),
   195  		Short: "send tokens by operator",
   196  		Long: strings.TrimSpace(fmt.Sprintf(`
   197  			$ %s tx %s operator-send-nft [contract-id] [operator] [from] [to] [amount]`, version.AppName, collection.ModuleName),
   198  		),
   199  		RunE: func(cmd *cobra.Command, args []string) error {
   200  			operator := args[1]
   201  			if err := cmd.Flags().Set(flags.FlagFrom, operator); err != nil {
   202  				return err
   203  			}
   204  
   205  			clientCtx, err := client.GetClientTxContext(cmd)
   206  			if err != nil {
   207  				return err
   208  			}
   209  
   210  			msg := collection.MsgOperatorSendNFT{
   211  				ContractId: args[0],
   212  				Operator:   operator,
   213  				From:       args[2],
   214  				To:         args[3],
   215  				TokenIds:   []string{args[4]},
   216  			}
   217  			if err := msg.ValidateBasic(); err != nil {
   218  				return err
   219  			}
   220  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   221  		},
   222  	}
   223  
   224  	flags.AddTxFlagsToCmd(cmd)
   225  	return cmd
   226  }
   227  
   228  func NewTxCmdCreateContract() *cobra.Command {
   229  	cmd := &cobra.Command{
   230  		Use:   "create-contract [creator]",
   231  		Args:  cobra.ExactArgs(1),
   232  		Short: "create a contract",
   233  		Long: strings.TrimSpace(fmt.Sprintf(`
   234  			$ %s tx %s create-contract [creator]`, version.AppName, collection.ModuleName),
   235  		),
   236  		RunE: func(cmd *cobra.Command, args []string) error {
   237  			creator := args[0]
   238  			if err := cmd.Flags().Set(flags.FlagFrom, creator); err != nil {
   239  				return err
   240  			}
   241  
   242  			clientCtx, err := client.GetClientTxContext(cmd)
   243  			if err != nil {
   244  				return err
   245  			}
   246  
   247  			name, err := cmd.Flags().GetString(FlagName)
   248  			if err != nil {
   249  				return err
   250  			}
   251  
   252  			baseImgURI, err := cmd.Flags().GetString(FlagBaseImgURI)
   253  			if err != nil {
   254  				return err
   255  			}
   256  
   257  			meta, err := cmd.Flags().GetString(FlagMeta)
   258  			if err != nil {
   259  				return err
   260  			}
   261  
   262  			msg := collection.MsgCreateContract{
   263  				Owner: creator,
   264  				Name:  name,
   265  				Uri:   baseImgURI,
   266  				Meta:  meta,
   267  			}
   268  			if err := msg.ValidateBasic(); err != nil {
   269  				return err
   270  			}
   271  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   272  		},
   273  	}
   274  
   275  	flags.AddTxFlagsToCmd(cmd)
   276  	cmd.Flags().String(FlagName, "", "set name")
   277  	cmd.Flags().String(FlagBaseImgURI, "", "set base-img-uri")
   278  	cmd.Flags().String(FlagMeta, "", "set meta")
   279  
   280  	return cmd
   281  }
   282  
   283  func NewTxCmdIssueFT() *cobra.Command {
   284  	cmd := &cobra.Command{
   285  		Use:   "issue-ft [contract-id] [operator]",
   286  		Args:  cobra.ExactArgs(2),
   287  		Short: "create a fungible token class",
   288  		Long: strings.TrimSpace(fmt.Sprintf(`
   289  			$ %s tx %s issue-ft [contract-id] [operator]`, version.AppName, collection.ModuleName),
   290  		),
   291  		RunE: func(cmd *cobra.Command, args []string) error {
   292  			operator := args[1]
   293  			if err := cmd.Flags().Set(flags.FlagFrom, operator); err != nil {
   294  				return err
   295  			}
   296  
   297  			clientCtx, err := client.GetClientTxContext(cmd)
   298  			if err != nil {
   299  				return err
   300  			}
   301  
   302  			name, err := cmd.Flags().GetString(FlagName)
   303  			if err != nil {
   304  				return err
   305  			}
   306  
   307  			meta, err := cmd.Flags().GetString(FlagMeta)
   308  			if err != nil {
   309  				return err
   310  			}
   311  
   312  			decimals, err := cmd.Flags().GetInt32(FlagDecimals)
   313  			if err != nil {
   314  				return err
   315  			}
   316  
   317  			mintable, err := cmd.Flags().GetBool(FlagMintable)
   318  			if err != nil {
   319  				return err
   320  			}
   321  
   322  			supplyStr, err := cmd.Flags().GetString(FlagSupply)
   323  			if err != nil {
   324  				return err
   325  			}
   326  			supply, ok := sdk.NewIntFromString(supplyStr)
   327  			if !ok {
   328  				return sdkerrors.ErrInvalidType.Wrapf("failed to set supply: %s", supplyStr)
   329  			}
   330  
   331  			to, err := cmd.Flags().GetString(FlagTo)
   332  			if err != nil {
   333  				return err
   334  			}
   335  
   336  			msg := collection.MsgIssueFT{
   337  				ContractId: args[0],
   338  				Owner:      operator,
   339  				Name:       name,
   340  				Meta:       meta,
   341  				Decimals:   decimals,
   342  				Mintable:   mintable,
   343  				To:         to,
   344  				Amount:     supply,
   345  			}
   346  			if err := msg.ValidateBasic(); err != nil {
   347  				return err
   348  			}
   349  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   350  		},
   351  	}
   352  
   353  	flags.AddTxFlagsToCmd(cmd)
   354  	cmd.Flags().String(FlagName, "", "set name")
   355  	cmd.MarkFlagRequired(FlagName)
   356  	cmd.Flags().String(FlagMeta, "", "set meta")
   357  	cmd.Flags().String(FlagTo, "", "address to send the initial supply")
   358  	cmd.MarkFlagRequired(FlagTo)
   359  	cmd.Flags().Bool(FlagMintable, false, "set mintable")
   360  	cmd.Flags().String(FlagSupply, DefaultSupply, "initial supply")
   361  	cmd.Flags().Int32(FlagDecimals, DefaultDecimals, "set decimals")
   362  
   363  	return cmd
   364  }
   365  
   366  func NewTxCmdIssueNFT() *cobra.Command {
   367  	cmd := &cobra.Command{
   368  		Use:   "issue-nft [contract-id] [operator]",
   369  		Args:  cobra.ExactArgs(2),
   370  		Short: "create a non-fungible token class",
   371  		Long: strings.TrimSpace(fmt.Sprintf(`
   372  			$ %s tx %s issue-nft [contract-id] [operator]`, version.AppName, collection.ModuleName),
   373  		),
   374  		RunE: func(cmd *cobra.Command, args []string) error {
   375  			operator := args[1]
   376  			if err := cmd.Flags().Set(flags.FlagFrom, operator); err != nil {
   377  				return err
   378  			}
   379  
   380  			clientCtx, err := client.GetClientTxContext(cmd)
   381  			if err != nil {
   382  				return err
   383  			}
   384  
   385  			name, err := cmd.Flags().GetString(FlagName)
   386  			if err != nil {
   387  				return err
   388  			}
   389  
   390  			meta, err := cmd.Flags().GetString(FlagMeta)
   391  			if err != nil {
   392  				return err
   393  			}
   394  
   395  			msg := collection.MsgIssueNFT{
   396  				ContractId: args[0],
   397  				Owner:      operator,
   398  				Name:       name,
   399  				Meta:       meta,
   400  			}
   401  			if err := msg.ValidateBasic(); err != nil {
   402  				return err
   403  			}
   404  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   405  		},
   406  	}
   407  
   408  	flags.AddTxFlagsToCmd(cmd)
   409  	cmd.Flags().String(FlagName, "", "set name")
   410  	cmd.Flags().String(FlagMeta, "", "set meta")
   411  
   412  	return cmd
   413  }
   414  
   415  func NewTxCmdMintFT() *cobra.Command {
   416  	cmd := &cobra.Command{
   417  		Use:   "mint-ft [contract-id] [operator] [to] [class-id] [amount]",
   418  		Args:  cobra.ExactArgs(5),
   419  		Short: "mint fungible tokens",
   420  		Long: strings.TrimSpace(fmt.Sprintf(`
   421  			$ %s tx %s mint-ft [contract-id] [operator] [to] [class-id] [amount]`, version.AppName, collection.ModuleName),
   422  		),
   423  		RunE: func(cmd *cobra.Command, args []string) error {
   424  			operator := args[1]
   425  			if err := cmd.Flags().Set(flags.FlagFrom, operator); err != nil {
   426  				return err
   427  			}
   428  
   429  			clientCtx, err := client.GetClientTxContext(cmd)
   430  			if err != nil {
   431  				return err
   432  			}
   433  
   434  			amountStr := args[4]
   435  			amount, ok := sdk.NewIntFromString(amountStr)
   436  			if !ok {
   437  				return sdkerrors.ErrInvalidType.Wrapf("failed to set amount: %s", amountStr)
   438  			}
   439  
   440  			coins := collection.NewCoins(collection.NewFTCoin(args[3], amount))
   441  			msg := collection.MsgMintFT{
   442  				ContractId: args[0],
   443  				From:       args[1],
   444  				To:         args[2],
   445  				Amount:     coins,
   446  			}
   447  			if err := msg.ValidateBasic(); err != nil {
   448  				return err
   449  			}
   450  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   451  		},
   452  	}
   453  
   454  	flags.AddTxFlagsToCmd(cmd)
   455  	return cmd
   456  }
   457  
   458  func NewTxCmdMintNFT() *cobra.Command {
   459  	cmd := &cobra.Command{
   460  		Use:   "mint-nft [contract-id] [operator] [to] [class-id]",
   461  		Args:  cobra.ExactArgs(4),
   462  		Short: "mint non-fungible tokens",
   463  		Long: strings.TrimSpace(fmt.Sprintf(`
   464  			$ %s tx %s mint-nft [contract-id] [operator] [to] [class-id]`, version.AppName, collection.ModuleName),
   465  		),
   466  		RunE: func(cmd *cobra.Command, args []string) error {
   467  			operator := args[1]
   468  			if err := cmd.Flags().Set(flags.FlagFrom, operator); err != nil {
   469  				return err
   470  			}
   471  
   472  			clientCtx, err := client.GetClientTxContext(cmd)
   473  			if err != nil {
   474  				return err
   475  			}
   476  
   477  			name, err := cmd.Flags().GetString(FlagName)
   478  			if err != nil {
   479  				return err
   480  			}
   481  
   482  			meta, err := cmd.Flags().GetString(FlagMeta)
   483  			if err != nil {
   484  				return err
   485  			}
   486  
   487  			params := []collection.MintNFTParam{{
   488  				TokenType: args[3],
   489  				Name:      name,
   490  				Meta:      meta,
   491  			}}
   492  
   493  			msg := collection.MsgMintNFT{
   494  				ContractId: args[0],
   495  				From:       args[1],
   496  				To:         args[2],
   497  				Params:     params,
   498  			}
   499  			if err := msg.ValidateBasic(); err != nil {
   500  				return err
   501  			}
   502  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   503  		},
   504  	}
   505  
   506  	flags.AddTxFlagsToCmd(cmd)
   507  	cmd.Flags().String(FlagName, "", "set name")
   508  	cmd.Flags().String(FlagMeta, "", "set meta")
   509  	cmd.MarkFlagRequired(FlagName)
   510  
   511  	return cmd
   512  }
   513  
   514  func NewTxCmdBurnFT() *cobra.Command {
   515  	cmd := &cobra.Command{
   516  		Use:   "burn-ft [contract-id] [from] [amount]",
   517  		Args:  cobra.ExactArgs(3),
   518  		Short: "burn tokens",
   519  		Long: strings.TrimSpace(fmt.Sprintf(`
   520  			$ %s tx %s burn-ft [contract-id] [from] [amount]`, version.AppName, collection.ModuleName),
   521  		),
   522  		RunE: func(cmd *cobra.Command, args []string) error {
   523  			from := args[1]
   524  			if err := cmd.Flags().Set(flags.FlagFrom, from); err != nil {
   525  				return err
   526  			}
   527  
   528  			clientCtx, err := client.GetClientTxContext(cmd)
   529  			if err != nil {
   530  				return err
   531  			}
   532  
   533  			amountStr := args[2]
   534  			amount, err := collection.ParseCoins(amountStr)
   535  			if err != nil {
   536  				return err
   537  			}
   538  
   539  			msg := collection.MsgBurnFT{
   540  				ContractId: args[0],
   541  				From:       from,
   542  				Amount:     amount,
   543  			}
   544  			if err := msg.ValidateBasic(); err != nil {
   545  				return err
   546  			}
   547  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   548  		},
   549  	}
   550  
   551  	flags.AddTxFlagsToCmd(cmd)
   552  	return cmd
   553  }
   554  
   555  func NewTxCmdOperatorBurnFT() *cobra.Command {
   556  	cmd := &cobra.Command{
   557  		Use:   "operator-burn-ft [contract-id] [operator] [from] [amount]",
   558  		Args:  cobra.ExactArgs(4),
   559  		Short: "burn tokens by a given operator",
   560  		Long: strings.TrimSpace(fmt.Sprintf(`
   561  			$ %s tx %s operator-burn-ft [contract-id] [operator] [from] [amount]`, version.AppName, collection.ModuleName),
   562  		),
   563  		RunE: func(cmd *cobra.Command, args []string) error {
   564  			operator := args[1]
   565  			if err := cmd.Flags().Set(flags.FlagFrom, operator); err != nil {
   566  				return err
   567  			}
   568  
   569  			clientCtx, err := client.GetClientTxContext(cmd)
   570  			if err != nil {
   571  				return err
   572  			}
   573  
   574  			amountStr := args[3]
   575  			amount, err := collection.ParseCoins(amountStr)
   576  			if err != nil {
   577  				return err
   578  			}
   579  
   580  			msg := collection.MsgOperatorBurnFT{
   581  				ContractId: args[0],
   582  				Operator:   operator,
   583  				From:       args[2],
   584  				Amount:     amount,
   585  			}
   586  			if err := msg.ValidateBasic(); err != nil {
   587  				return err
   588  			}
   589  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   590  		},
   591  	}
   592  
   593  	flags.AddTxFlagsToCmd(cmd)
   594  	return cmd
   595  }
   596  
   597  func NewTxCmdBurnNFT() *cobra.Command {
   598  	cmd := &cobra.Command{
   599  		Use:   "burn-nft [contract-id] [from] [token-id]",
   600  		Args:  cobra.ExactArgs(3),
   601  		Short: "burn tokens",
   602  		Long: strings.TrimSpace(fmt.Sprintf(`
   603  			$ %s tx %s burn-nft [contract-id] [from] [token-id]`, version.AppName, collection.ModuleName),
   604  		),
   605  		RunE: func(cmd *cobra.Command, args []string) error {
   606  			from := args[1]
   607  			if err := cmd.Flags().Set(flags.FlagFrom, from); err != nil {
   608  				return err
   609  			}
   610  
   611  			clientCtx, err := client.GetClientTxContext(cmd)
   612  			if err != nil {
   613  				return err
   614  			}
   615  
   616  			msg := collection.MsgBurnNFT{
   617  				ContractId: args[0],
   618  				From:       from,
   619  				TokenIds:   []string{args[2]},
   620  			}
   621  			if err := msg.ValidateBasic(); err != nil {
   622  				return err
   623  			}
   624  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   625  		},
   626  	}
   627  
   628  	flags.AddTxFlagsToCmd(cmd)
   629  	return cmd
   630  }
   631  
   632  func NewTxCmdOperatorBurnNFT() *cobra.Command {
   633  	cmd := &cobra.Command{
   634  		Use:   "operator-burn-nft [contract-id] [operator] [from] [token-id]",
   635  		Args:  cobra.ExactArgs(4),
   636  		Short: "burn tokens by a given operator",
   637  		Long: strings.TrimSpace(fmt.Sprintf(`
   638  			$ %s tx %s operator-burn-nft [contract-id] [operator] [from] [token-id]`, version.AppName, collection.ModuleName),
   639  		),
   640  		RunE: func(cmd *cobra.Command, args []string) error {
   641  			operator := args[1]
   642  			if err := cmd.Flags().Set(flags.FlagFrom, operator); err != nil {
   643  				return err
   644  			}
   645  
   646  			clientCtx, err := client.GetClientTxContext(cmd)
   647  			if err != nil {
   648  				return err
   649  			}
   650  
   651  			msg := collection.MsgOperatorBurnNFT{
   652  				ContractId: args[0],
   653  				Operator:   operator,
   654  				From:       args[2],
   655  				TokenIds:   []string{args[3]},
   656  			}
   657  			if err := msg.ValidateBasic(); err != nil {
   658  				return err
   659  			}
   660  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   661  		},
   662  	}
   663  
   664  	flags.AddTxFlagsToCmd(cmd)
   665  	return cmd
   666  }
   667  
   668  func NewTxCmdModify() *cobra.Command {
   669  	cmd := &cobra.Command{
   670  		Use:   "modify [contract-id] [operator] [token-type] [token-index] [key] [value]",
   671  		Args:  cobra.ExactArgs(6),
   672  		Short: "modify",
   673  		Long: strings.TrimSpace(fmt.Sprintf(`
   674  			$ %s tx %s modify [contract-id] [operator] [token-type] [token-index] [key] [value]`, version.AppName, collection.ModuleName),
   675  		),
   676  		RunE: func(cmd *cobra.Command, args []string) error {
   677  			operator := args[1]
   678  			if err := cmd.Flags().Set(flags.FlagFrom, operator); err != nil {
   679  				return err
   680  			}
   681  
   682  			clientCtx, err := client.GetClientTxContext(cmd)
   683  			if err != nil {
   684  				return err
   685  			}
   686  
   687  			changes := []collection.Attribute{{
   688  				Key:   args[4],
   689  				Value: args[5],
   690  			}}
   691  			msg := collection.MsgModify{
   692  				ContractId: args[0],
   693  				Owner:      args[1],
   694  				TokenType:  args[2],
   695  				TokenIndex: args[3],
   696  				Changes:    changes,
   697  			}
   698  			if err := msg.ValidateBasic(); err != nil {
   699  				return err
   700  			}
   701  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   702  		},
   703  	}
   704  
   705  	flags.AddTxFlagsToCmd(cmd)
   706  	return cmd
   707  }
   708  
   709  func NewTxCmdAttach() *cobra.Command {
   710  	cmd := &cobra.Command{
   711  		Use:   "attach [contract-id] [holder] [subject] [target]",
   712  		Args:  cobra.ExactArgs(4),
   713  		Short: "attach a token to another",
   714  		Long: strings.TrimSpace(fmt.Sprintf(`
   715  			$ %s tx %s attach [contract-id] [holder] [subject] [target]`, version.AppName, collection.ModuleName),
   716  		),
   717  		RunE: func(cmd *cobra.Command, args []string) error {
   718  			holder := args[1]
   719  			if err := cmd.Flags().Set(flags.FlagFrom, holder); err != nil {
   720  				return err
   721  			}
   722  
   723  			clientCtx, err := client.GetClientTxContext(cmd)
   724  			if err != nil {
   725  				return err
   726  			}
   727  
   728  			msg := collection.MsgAttach{
   729  				ContractId: args[0],
   730  				From:       holder,
   731  				TokenId:    args[2],
   732  				ToTokenId:  args[3],
   733  			}
   734  			if err := msg.ValidateBasic(); err != nil {
   735  				return err
   736  			}
   737  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   738  		},
   739  	}
   740  
   741  	flags.AddTxFlagsToCmd(cmd)
   742  	return cmd
   743  }
   744  
   745  func NewTxCmdDetach() *cobra.Command {
   746  	cmd := &cobra.Command{
   747  		Use:   "detach [contract-id] [holder] [subject]",
   748  		Args:  cobra.ExactArgs(3),
   749  		Short: "detach a token from its parent",
   750  		Long: strings.TrimSpace(fmt.Sprintf(`
   751  			$ %s tx %s detach [contract-id] [holder] [subject]`, version.AppName, collection.ModuleName),
   752  		),
   753  		RunE: func(cmd *cobra.Command, args []string) error {
   754  			holder := args[1]
   755  			if err := cmd.Flags().Set(flags.FlagFrom, holder); err != nil {
   756  				return err
   757  			}
   758  
   759  			clientCtx, err := client.GetClientTxContext(cmd)
   760  			if err != nil {
   761  				return err
   762  			}
   763  
   764  			msg := collection.MsgDetach{
   765  				ContractId: args[0],
   766  				From:       holder,
   767  				TokenId:    args[2],
   768  			}
   769  			if err := msg.ValidateBasic(); err != nil {
   770  				return err
   771  			}
   772  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   773  		},
   774  	}
   775  
   776  	flags.AddTxFlagsToCmd(cmd)
   777  	return cmd
   778  }
   779  
   780  func NewTxCmdOperatorAttach() *cobra.Command {
   781  	cmd := &cobra.Command{
   782  		Use:   "operator-attach [contract-id] [operator] [holder] [subject] [target]",
   783  		Args:  cobra.ExactArgs(5),
   784  		Short: "attach a token to another by the operator",
   785  		Long: strings.TrimSpace(fmt.Sprintf(`
   786  			$ %s tx %s operator-attach [contract-id] [operator] [holder] [subject] [target]`, version.AppName, collection.ModuleName),
   787  		),
   788  		RunE: func(cmd *cobra.Command, args []string) error {
   789  			operator := args[1]
   790  			if err := cmd.Flags().Set(flags.FlagFrom, operator); err != nil {
   791  				return err
   792  			}
   793  
   794  			clientCtx, err := client.GetClientTxContext(cmd)
   795  			if err != nil {
   796  				return err
   797  			}
   798  
   799  			msg := collection.MsgOperatorAttach{
   800  				ContractId: args[0],
   801  				Operator:   operator,
   802  				From:       args[2],
   803  				TokenId:    args[3],
   804  				ToTokenId:  args[4],
   805  			}
   806  			if err := msg.ValidateBasic(); err != nil {
   807  				return err
   808  			}
   809  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   810  		},
   811  	}
   812  
   813  	flags.AddTxFlagsToCmd(cmd)
   814  	return cmd
   815  }
   816  
   817  func NewTxCmdOperatorDetach() *cobra.Command {
   818  	cmd := &cobra.Command{
   819  		Use:   "operator-detach [contract-id] [operator] [holder] [subject]",
   820  		Args:  cobra.ExactArgs(4),
   821  		Short: "detach a token from its parent by the operator",
   822  		Long: strings.TrimSpace(fmt.Sprintf(`
   823  			$ %s tx %s operator-detach [contract-id] [operator] [holder] [subject]`, version.AppName, collection.ModuleName),
   824  		),
   825  		RunE: func(cmd *cobra.Command, args []string) error {
   826  			operator := args[1]
   827  			if err := cmd.Flags().Set(flags.FlagFrom, operator); err != nil {
   828  				return err
   829  			}
   830  
   831  			clientCtx, err := client.GetClientTxContext(cmd)
   832  			if err != nil {
   833  				return err
   834  			}
   835  
   836  			msg := collection.MsgOperatorDetach{
   837  				ContractId: args[0],
   838  				Operator:   operator,
   839  				From:       args[2],
   840  				TokenId:    args[3],
   841  			}
   842  			if err := msg.ValidateBasic(); err != nil {
   843  				return err
   844  			}
   845  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   846  		},
   847  	}
   848  
   849  	flags.AddTxFlagsToCmd(cmd)
   850  	return cmd
   851  }
   852  
   853  func NewTxCmdGrantPermission() *cobra.Command {
   854  	cmd := &cobra.Command{
   855  		Use:   "grant-permission [contract-id] [granter] [grantee] [permission]",
   856  		Args:  cobra.ExactArgs(4),
   857  		Short: "grant a permission for mint, burn, modify and issue",
   858  		Long: strings.TrimSpace(fmt.Sprintf(`
   859  			$ %s tx %s grant-permission [contract-id] [granter] [grantee] [permission]`, version.AppName, collection.ModuleName),
   860  		),
   861  		RunE: func(cmd *cobra.Command, args []string) error {
   862  			granter := args[1]
   863  			if err := cmd.Flags().Set(flags.FlagFrom, granter); err != nil {
   864  				return err
   865  			}
   866  
   867  			clientCtx, err := client.GetClientTxContext(cmd)
   868  			if err != nil {
   869  				return err
   870  			}
   871  
   872  			msg := collection.MsgGrantPermission{
   873  				ContractId: args[0],
   874  				From:       granter,
   875  				To:         args[2],
   876  				Permission: args[3],
   877  			}
   878  			if err := msg.ValidateBasic(); err != nil {
   879  				return err
   880  			}
   881  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   882  		},
   883  	}
   884  
   885  	flags.AddTxFlagsToCmd(cmd)
   886  	return cmd
   887  }
   888  
   889  func NewTxCmdRevokePermission() *cobra.Command {
   890  	cmd := &cobra.Command{
   891  		Use:   "revoke-permission [contract-id] [grantee] [permission]",
   892  		Args:  cobra.ExactArgs(3),
   893  		Short: "revoke a permission by a given grantee",
   894  		Long: strings.TrimSpace(fmt.Sprintf(`
   895  			$ %s tx %s revoke-permission [contract-id] [grantee] [permission]`, version.AppName, collection.ModuleName),
   896  		),
   897  		RunE: func(cmd *cobra.Command, args []string) error {
   898  			grantee := args[1]
   899  			if err := cmd.Flags().Set(flags.FlagFrom, grantee); err != nil {
   900  				return err
   901  			}
   902  
   903  			clientCtx, err := client.GetClientTxContext(cmd)
   904  			if err != nil {
   905  				return err
   906  			}
   907  
   908  			msg := collection.MsgRevokePermission{
   909  				ContractId: args[0],
   910  				From:       grantee,
   911  				Permission: args[2],
   912  			}
   913  			if err := msg.ValidateBasic(); err != nil {
   914  				return err
   915  			}
   916  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   917  		},
   918  	}
   919  
   920  	flags.AddTxFlagsToCmd(cmd)
   921  	return cmd
   922  }
   923  
   924  func NewTxCmdAuthorizeOperator() *cobra.Command {
   925  	cmd := &cobra.Command{
   926  		Use:   "authorize-operator [contract-id] [holder] [operator]",
   927  		Args:  cobra.ExactArgs(3),
   928  		Short: "authorize operator to manipulate tokens of holder",
   929  		Long: strings.TrimSpace(fmt.Sprintf(`
   930  			$ %s tx %s authorize-operator [contract-id] [holder] [operator]`, version.AppName, collection.ModuleName),
   931  		),
   932  		RunE: func(cmd *cobra.Command, args []string) error {
   933  			holder := args[1]
   934  			if err := cmd.Flags().Set(flags.FlagFrom, holder); err != nil {
   935  				return err
   936  			}
   937  
   938  			clientCtx, err := client.GetClientTxContext(cmd)
   939  			if err != nil {
   940  				return err
   941  			}
   942  
   943  			msg := collection.MsgAuthorizeOperator{
   944  				ContractId: args[0],
   945  				Holder:     holder,
   946  				Operator:   args[2],
   947  			}
   948  			if err := msg.ValidateBasic(); err != nil {
   949  				return err
   950  			}
   951  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   952  		},
   953  	}
   954  
   955  	flags.AddTxFlagsToCmd(cmd)
   956  	return cmd
   957  }
   958  
   959  func NewTxCmdRevokeOperator() *cobra.Command {
   960  	cmd := &cobra.Command{
   961  		Use:   "revoke-operator [contract-id] [holder] [operator]",
   962  		Args:  cobra.ExactArgs(3),
   963  		Short: "revoke operator",
   964  		Long: strings.TrimSpace(fmt.Sprintf(`
   965  			$ %s tx %s revoke-operator [contract-id] [holder] [operator]`, version.AppName, collection.ModuleName),
   966  		),
   967  		RunE: func(cmd *cobra.Command, args []string) error {
   968  			holder := args[1]
   969  			if err := cmd.Flags().Set(flags.FlagFrom, holder); err != nil {
   970  				return err
   971  			}
   972  
   973  			clientCtx, err := client.GetClientTxContext(cmd)
   974  			if err != nil {
   975  				return err
   976  			}
   977  
   978  			msg := collection.MsgRevokeOperator{
   979  				ContractId: args[0],
   980  				Holder:     holder,
   981  				Operator:   args[2],
   982  			}
   983  			if err := msg.ValidateBasic(); err != nil {
   984  				return err
   985  			}
   986  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   987  		},
   988  	}
   989  
   990  	flags.AddTxFlagsToCmd(cmd)
   991  	return cmd
   992  }