github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/token/client/cli/tx.go (about)

     1  package cli
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/flags"
     7  	"io/ioutil"
     8  	"strings"
     9  
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client"
    11  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/context"
    12  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    13  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    14  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth"
    15  	authTypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth"
    16  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/client/utils"
    17  	"github.com/fibonacci-chain/fbc/x/token/types"
    18  	"github.com/pkg/errors"
    19  	"github.com/spf13/cobra"
    20  )
    21  
    22  const (
    23  	From          = "from"
    24  	To            = "to"
    25  	Sign          = "sign"
    26  	Amount        = "amount"
    27  	TotalSupply   = "total-supply"
    28  	Symbol        = "symbol"
    29  	WholeName     = "whole-name"
    30  	TokenDesc     = "desc"
    31  	Mintable      = "mintable"
    32  	Transfers     = "transfers"
    33  	TransfersFile = "transfers-file"
    34  )
    35  
    36  const (
    37  	TokenDescLenLimit = 256
    38  )
    39  
    40  var (
    41  	errSymbolNotValid         = errors.New("symbol not valid")
    42  	errTotalSupplyNotValid    = errors.New("total-supply not valid")
    43  	errFromNotValid           = errors.New("from not valid")
    44  	errAmountNotValid         = errors.New("amount not valid")
    45  	errTokenDescNotValid      = errors.New("token-desc not valid")
    46  	errTokenWholeNameNotValid = errors.New("token whole name not valid")
    47  	errMintableNotValid       = errors.New("mintable not valid")
    48  	errTransfersNotValid      = errors.New("transfers not valid")
    49  	errTransfersFileNotValid  = errors.New("transfers file not valid")
    50  	errSign                   = errors.New("sign not succeed")
    51  	errParam                  = errors.New("can't get token desc or whole name")
    52  )
    53  
    54  // GetTxCmd returns the transaction commands for this module
    55  func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command {
    56  	distTxCmd := &cobra.Command{
    57  		Use:                        types.ModuleName,
    58  		Short:                      "Token transactions subcommands",
    59  		DisableFlagParsing:         true,
    60  		SuggestionsMinimumDistance: 2,
    61  		RunE:                       client.ValidateCmd,
    62  	}
    63  
    64  	distTxCmd.AddCommand(flags.PostCommands(
    65  		getCmdTokenIssue(cdc),
    66  		getCmdTokenBurn(cdc),
    67  		getCmdTokenMint(cdc),
    68  		getCmdTokenMultiSend(cdc),
    69  		getCmdTransferOwnership(cdc),
    70  		getCmdConfirmOwnership(cdc),
    71  		getCmdTokenEdit(cdc),
    72  	)...)
    73  
    74  	return distTxCmd
    75  }
    76  
    77  // getCmdTokenIssue is the CLI command for sending a IssueToken transaction
    78  func getCmdTokenIssue(cdc *codec.Codec) *cobra.Command {
    79  	cmd := &cobra.Command{
    80  		Use:   "issue",
    81  		Short: "issue a token",
    82  		//Args:  cobra.ExactArgs(2),
    83  		RunE: func(cmd *cobra.Command, args []string) error {
    84  
    85  			cliCtx := context.NewCLIContext().WithCodec(cdc)
    86  			inBuf := bufio.NewReader(cmd.InOrStdin())
    87  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
    88  
    89  			if err := authTypes.NewAccountRetriever(cliCtx).EnsureExists(cliCtx.FromAddress); err != nil {
    90  				return err
    91  			}
    92  
    93  			flags := cmd.Flags()
    94  
    95  			// params check
    96  			originalSymbol, err := flags.GetString(Symbol)
    97  			originalSymbol = strings.ToLower(originalSymbol)
    98  			if err != nil {
    99  				return errSymbolNotValid
   100  			}
   101  			_, err = flags.GetString(From)
   102  			if err != nil {
   103  				return errFromNotValid
   104  			}
   105  			totalSupply, err := flags.GetString(TotalSupply)
   106  			if err != nil {
   107  				return errTotalSupplyNotValid
   108  			}
   109  			tokenDesc, err := flags.GetString(TokenDesc)
   110  			if err != nil || len(tokenDesc) > TokenDescLenLimit {
   111  				return errTokenDescNotValid
   112  			}
   113  
   114  			wholeName, err := flags.GetString(WholeName)
   115  			if err != nil {
   116  				return errTokenWholeNameNotValid
   117  			}
   118  			// check wholeName
   119  			var isValid bool
   120  			wholeName, isValid = types.WholeNameCheck(wholeName)
   121  			if !isValid {
   122  				return errTokenWholeNameNotValid
   123  			}
   124  
   125  			mintable, err := flags.GetBool(Mintable)
   126  			if err != nil {
   127  				return errMintableNotValid
   128  			}
   129  
   130  			var symbol string
   131  
   132  			// totalSupply int64 ,coins bigint
   133  			msg := types.NewMsgTokenIssue(tokenDesc, symbol, originalSymbol, wholeName, totalSupply, cliCtx.FromAddress, mintable)
   134  
   135  			return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
   136  		},
   137  	}
   138  
   139  	cmd.Flags().StringP(Symbol, "s", "", "symbol of the new token")
   140  	cmd.Flags().StringP(WholeName, "w", "", "whole name of the new token")
   141  	cmd.Flags().String(TokenDesc, "", "describe of the token")
   142  	cmd.Flags().StringP(TotalSupply, "n", "0", "total supply of the new token")
   143  	cmd.Flags().Bool(Mintable, false, "whether the token can be minted")
   144  
   145  	return cmd
   146  }
   147  
   148  // getCmdTokenBurn is the CLI command for sending a BurnToken transaction
   149  func getCmdTokenBurn(cdc *codec.Codec) *cobra.Command {
   150  	cmd := &cobra.Command{
   151  		Use:   "burn [amount]",
   152  		Short: "burn some amount of token",
   153  		Args:  cobra.ExactArgs(1),
   154  		RunE: func(cmd *cobra.Command, args []string) error {
   155  
   156  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   157  			inBuf := bufio.NewReader(cmd.InOrStdin())
   158  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   159  
   160  			if err := authTypes.NewAccountRetriever(cliCtx).EnsureExists(cliCtx.FromAddress); err != nil {
   161  				return err
   162  			}
   163  
   164  			// params check
   165  			flags := cmd.Flags()
   166  
   167  			amount, err := sdk.ParseDecCoin(args[0])
   168  			if err != nil {
   169  				return err
   170  			}
   171  
   172  			_, err = flags.GetString(From)
   173  			if err != nil {
   174  				return err
   175  			}
   176  
   177  			msg := types.NewMsgTokenBurn(amount, cliCtx.FromAddress)
   178  
   179  			return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
   180  		},
   181  	}
   182  	return cmd
   183  }
   184  
   185  // getCmdTokenMint is the CLI command for sending a MintToken transaction
   186  func getCmdTokenMint(cdc *codec.Codec) *cobra.Command {
   187  	cmd := &cobra.Command{
   188  		Use:   "mint [amount]",
   189  		Short: "mint tokens for an existing token",
   190  		Args:  cobra.ExactArgs(1),
   191  		RunE: func(cmd *cobra.Command, args []string) error {
   192  
   193  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   194  			inBuf := bufio.NewReader(cmd.InOrStdin())
   195  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   196  			if err := authTypes.NewAccountRetriever(cliCtx).EnsureExists(cliCtx.FromAddress); err != nil {
   197  				return err
   198  			}
   199  			flags := cmd.Flags()
   200  
   201  			amount, err := sdk.ParseDecCoin(args[0])
   202  			if err != nil {
   203  				return err
   204  			}
   205  
   206  			_, err = flags.GetString(From)
   207  			if err != nil {
   208  				return errFromNotValid
   209  			}
   210  
   211  			msg := types.NewMsgTokenMint(amount, cliCtx.FromAddress)
   212  
   213  			return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
   214  		},
   215  	}
   216  	return cmd
   217  }
   218  
   219  // getCmdTokenMultiSend is the CLI command for sending a MultiSend transaction
   220  func getCmdTokenMultiSend(cdc *codec.Codec) *cobra.Command {
   221  	cmd := &cobra.Command{
   222  		Use:   "multi-send",
   223  		Short: "Create and sign a multi send tx",
   224  		//Args:  cobra.ExactArgs(2),
   225  		RunE: func(cmd *cobra.Command, args []string) error {
   226  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   227  			inBuf := bufio.NewReader(cmd.InOrStdin())
   228  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   229  			if err := authTypes.NewAccountRetriever(cliCtx).EnsureExists(cliCtx.FromAddress); err != nil {
   230  				return err
   231  			}
   232  			flags := cmd.Flags()
   233  
   234  			_, err := flags.GetString(From)
   235  			if err != nil {
   236  				return errFromNotValid
   237  			}
   238  			transferStr, err := flags.GetString(Transfers)
   239  			if err != nil {
   240  				return errTransfersNotValid
   241  			}
   242  
   243  			transfersFile, err := flags.GetString(TransfersFile)
   244  			if err != nil {
   245  				return errTransfersFileNotValid
   246  			}
   247  
   248  			var transfers []types.TransferUnit
   249  			if transferStr != "" {
   250  				transfers, err = types.StrToTransfers(transferStr)
   251  				if err != nil {
   252  					return err
   253  				}
   254  			}
   255  
   256  			if transfersFile != "" {
   257  				transferBytes, err := ioutil.ReadFile(transfersFile)
   258  				if err != nil {
   259  					return err
   260  				}
   261  				transferStr = string(transferBytes)
   262  				//return errors.New(transferStr)
   263  				transfers, err = types.StrToTransfers(transferStr)
   264  				if err != nil {
   265  					return err
   266  				}
   267  			}
   268  
   269  			for _, transfer := range transfers {
   270  				if transfer.To.Equals(cliCtx.GetFromAddress()) {
   271  					return errors.New(transfer.To.String())
   272  					//return errors.New("can not transfer coins to yourself")
   273  				}
   274  			}
   275  
   276  			msg := types.NewMsgMultiSend(cliCtx.FromAddress, transfers)
   277  
   278  			return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
   279  		},
   280  	}
   281  	cmd.Flags().String(Transfers, "", `Transfers details, format: [{"to": "addr", "amount": "1fibo,2btc"}, ...]`)
   282  	cmd.Flags().String(TransfersFile, "", "File of transfers details, if transfers-file is not empty, --transfers will be ignore")
   283  	//cmd.MarkFlagRequired(Amount)
   284  	return cmd
   285  }
   286  
   287  // getCmdTransferOwnership is the CLI command for sending a ChangeOwner transaction
   288  func getCmdTransferOwnership(cdc *codec.Codec) *cobra.Command {
   289  	cmd := &cobra.Command{
   290  		Use:   "transfer-ownership",
   291  		Short: "change the owner of the token",
   292  		RunE: func(cmd *cobra.Command, args []string) error {
   293  
   294  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   295  			inBuf := bufio.NewReader(cmd.InOrStdin())
   296  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   297  			if err := authTypes.NewAccountRetriever(cliCtx).EnsureExists(cliCtx.FromAddress); err != nil {
   298  				return err
   299  			}
   300  			flags := cmd.Flags()
   301  
   302  			symbol, err := flags.GetString(Symbol)
   303  			if err != nil {
   304  				return errSymbolNotValid
   305  			}
   306  			_, err = flags.GetString(From)
   307  			if err != nil {
   308  				return errFromNotValid
   309  			}
   310  			to, err := flags.GetString(To)
   311  			if err != nil {
   312  				return errAmountNotValid
   313  			}
   314  
   315  			from := cliCtx.GetFromAddress()
   316  
   317  			toBytes, err := sdk.AccAddressFromBech32(to)
   318  			if err != nil {
   319  				return errFromNotValid
   320  			}
   321  
   322  			msg := types.NewMsgTransferOwnership(from, toBytes, symbol)
   323  			return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
   324  		},
   325  	}
   326  	cmd.Flags().StringP("symbol", "s", "", "symbol of the token to be transferred")
   327  	cmd.Flags().String("to", "", "the user to be transferred")
   328  	return cmd
   329  }
   330  
   331  // SendTxCmd will create a transaction to send and sign
   332  func SendTxCmd(cdc *codec.Codec) *cobra.Command {
   333  	cmd := &cobra.Command{
   334  		Use:   "send [from_key_or_address] [to_address] [amount]",
   335  		Short: "Create and sign a send tx",
   336  		Args:  cobra.ExactArgs(3),
   337  		RunE: func(cmd *cobra.Command, args []string) error {
   338  			inBuf := bufio.NewReader(cmd.InOrStdin())
   339  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   340  			cliCtx := context.NewCLIContextWithFrom(args[0]).WithCodec(cdc)
   341  
   342  			to, err := sdk.AccAddressFromBech32(args[1])
   343  			if err != nil {
   344  				return fmt.Errorf("invalid address:%s", args[1])
   345  			}
   346  
   347  			coins, err := sdk.ParseDecCoins(args[2])
   348  			if err != nil {
   349  				return err
   350  			}
   351  
   352  			// build and sign the transaction, then broadcast to Tendermint
   353  			msg := types.NewMsgTokenSend(cliCtx.GetFromAddress(), to, coins)
   354  			return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
   355  		},
   356  	}
   357  
   358  	cmd = flags.PostCommands(cmd)[0]
   359  
   360  	return cmd
   361  }
   362  
   363  // getCmdTokenEdit is the CLI command for sending a TokenEdit transaction
   364  func getCmdTokenEdit(cdc *codec.Codec) *cobra.Command {
   365  	cmd := &cobra.Command{
   366  		Use:   "edit",
   367  		Short: "edit a token's whole name and desc",
   368  		//Args:  cobra.ExactArgs(2),
   369  		RunE: func(cmd *cobra.Command, args []string) error {
   370  
   371  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   372  			inBuf := bufio.NewReader(cmd.InOrStdin())
   373  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   374  
   375  			if err := authTypes.NewAccountRetriever(cliCtx).EnsureExists(cliCtx.FromAddress); err != nil {
   376  				return err
   377  			}
   378  
   379  			flags := cmd.Flags()
   380  
   381  			// params check
   382  			symbol, err := flags.GetString(Symbol)
   383  			if err != nil {
   384  				return errSymbolNotValid
   385  			}
   386  			_, err = flags.GetString(From)
   387  			if err != nil {
   388  				return errFromNotValid
   389  			}
   390  
   391  			var isDescEdit, isWholeNameEdit bool
   392  			var tokenDesc, wholeName string
   393  			dcEditFlag := flags.Lookup(TokenDesc)
   394  			if dcEditFlag != nil && dcEditFlag.Changed {
   395  				isDescEdit = true
   396  				tokenDesc, err = flags.GetString(TokenDesc)
   397  				if err != nil || len(tokenDesc) > TokenDescLenLimit {
   398  					return errTokenDescNotValid
   399  				}
   400  			}
   401  			wnEditFlag := flags.Lookup(WholeName)
   402  			if wnEditFlag != nil && wnEditFlag.Changed {
   403  				isWholeNameEdit = true
   404  				wholeName, err = flags.GetString(WholeName)
   405  				if err != nil {
   406  					return errTokenWholeNameNotValid
   407  				}
   408  				// check wholeName
   409  				var isValid bool
   410  				wholeName, isValid = types.WholeNameCheck(wholeName)
   411  				if !isValid {
   412  					return errTokenWholeNameNotValid
   413  				}
   414  			}
   415  			if !isWholeNameEdit && !isDescEdit {
   416  				return errParam
   417  			}
   418  
   419  			msg := types.NewMsgTokenModify(symbol, tokenDesc, wholeName, isDescEdit, isWholeNameEdit, cliCtx.FromAddress)
   420  			return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
   421  		},
   422  	}
   423  	cmd.Flags().StringP(Symbol, "s", "", "symbol of the token")
   424  	cmd.Flags().StringP(WholeName, "w", "", "whole name of the token")
   425  	cmd.Flags().String(TokenDesc, "", "description of the token")
   426  
   427  	return cmd
   428  }
   429  
   430  // getCmdConfirmOwnership is the CLI command for sending a ConfirmOwnership transaction
   431  func getCmdConfirmOwnership(cdc *codec.Codec) *cobra.Command {
   432  	cmd := &cobra.Command{
   433  		Use:   "confirm-ownership",
   434  		Short: "confirm the transfer-ownership of the token",
   435  		RunE: func(cmd *cobra.Command, args []string) error {
   436  
   437  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   438  			inBuf := bufio.NewReader(cmd.InOrStdin())
   439  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   440  			if err := authTypes.NewAccountRetriever(cliCtx).EnsureExists(cliCtx.FromAddress); err != nil {
   441  				return err
   442  			}
   443  			flags := cmd.Flags()
   444  
   445  			symbol, err := flags.GetString(Symbol)
   446  			if err != nil {
   447  				return errSymbolNotValid
   448  			}
   449  			_, err = flags.GetString(From)
   450  			if err != nil {
   451  				return errFromNotValid
   452  			}
   453  
   454  			from := cliCtx.GetFromAddress()
   455  
   456  			msg := types.NewMsgConfirmOwnership(from, symbol)
   457  			return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
   458  		},
   459  	}
   460  	cmd.Flags().StringP("symbol", "s", "", "symbol of the token to be transferred")
   461  	return cmd
   462  }