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 }