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

     1  package cli
     2  
     3  import (
     4  	"bufio"
     5  	"encoding/json"
     6  	"fmt"
     7  	"strings"
     8  
     9  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client"
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/context"
    11  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/flags"
    12  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    13  	interfacetypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec/types"
    14  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    15  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/version"
    16  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth"
    17  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/client/utils"
    18  	fsutils "github.com/fibonacci-chain/fbc/x/feesplit/client/utils"
    19  	"github.com/fibonacci-chain/fbc/x/feesplit/types"
    20  	govTypes "github.com/fibonacci-chain/fbc/x/gov/types"
    21  
    22  	"github.com/spf13/cobra"
    23  )
    24  
    25  // GetTxCmd returns a root CLI command handler for certain modules/feesplit
    26  // transaction commands.
    27  func GetTxCmd(cdc *codec.Codec) *cobra.Command {
    28  	cmd := &cobra.Command{
    29  		Use:                        types.ModuleName,
    30  		Short:                      "feesplit subcommands",
    31  		DisableFlagParsing:         true,
    32  		SuggestionsMinimumDistance: 2,
    33  		RunE:                       client.ValidateCmd,
    34  	}
    35  
    36  	cmd.AddCommand(flags.PostCommands(
    37  		GetRegisterFeeSplit(cdc),
    38  		GetCancelFeeSplit(cdc),
    39  		GetUpdateFeeSplit(cdc),
    40  	)...)
    41  	return cmd
    42  }
    43  
    44  // GetRegisterFeeSplit returns a CLI command handler for registering a
    45  // contract for fee distribution
    46  func GetRegisterFeeSplit(cdc *codec.Codec) *cobra.Command {
    47  	cmd := &cobra.Command{
    48  		Use:   "register [contract_hex] [nonces] [withdraw_bech32]",
    49  		Short: "Register a contract for fee distribution. **NOTE** Please ensure, that the deployer of the contract (or the factory that deployes the contract) is an account that is owned by your project, to avoid that an individual deployer who leaves your project becomes malicious.",
    50  		Long:  "Register a contract for fee distribution.\nOnly the contract deployer can register a contract.\nProvide the account nonce(s) used to derive the contract address. E.g.: you have an account nonce of 4 when you send a deployment transaction for a contract A; you use this contract as a factory, to create another contract B. If you register A, the nonces value is \"4\". If you register B, the nonces value is \"4,1\" (B is the first contract created by A). \nThe withdraw address defaults to the deployer address if not provided.",
    51  		Args:  cobra.RangeArgs(2, 3),
    52  		RunE: func(cmd *cobra.Command, args []string) error {
    53  			inBuf := bufio.NewReader(cmd.InOrStdin())
    54  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
    55  			cliCtx := context.NewCLIContext().WithCodec(cdc)
    56  
    57  			var withdraw string
    58  			deployer := cliCtx.GetFromAddress()
    59  
    60  			contract := args[0]
    61  			if err := types.ValidateNonZeroAddress(contract); err != nil {
    62  				return fmt.Errorf("invalid contract hex address %w", err)
    63  			}
    64  
    65  			var nonces []uint64
    66  			if err := json.Unmarshal([]byte("["+args[1]+"]"), &nonces); err != nil {
    67  				return fmt.Errorf("invalid nonces %w", err)
    68  			}
    69  
    70  			if len(args) == 3 {
    71  				withdraw = args[2]
    72  				if _, err := sdk.AccAddressFromBech32(withdraw); err != nil {
    73  					return fmt.Errorf("invalid withdraw bech32 address %w", err)
    74  				}
    75  			}
    76  
    77  			if withdraw == "" {
    78  				withdraw = deployer.String()
    79  			}
    80  
    81  			msg := &types.MsgRegisterFeeSplit{
    82  				ContractAddress:   contract,
    83  				DeployerAddress:   deployer.String(),
    84  				WithdrawerAddress: withdraw,
    85  				Nonces:            nonces,
    86  			}
    87  			if err := msg.ValidateBasic(); err != nil {
    88  				return err
    89  			}
    90  
    91  			return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
    92  		},
    93  	}
    94  
    95  	return cmd
    96  }
    97  
    98  // GetCancelFeeSplit returns a CLI command handler for canceling a
    99  // contract for fee distribution
   100  func GetCancelFeeSplit(cdc *codec.Codec) *cobra.Command {
   101  	cmd := &cobra.Command{
   102  		Use:   "cancel [contract_hex]",
   103  		Short: "Cancel a contract from fee distribution",
   104  		Long:  "Cancel a contract from fee distribution. The deployer will no longer receive fees from users interacting with the contract. \nOnly the contract deployer can cancel a contract.",
   105  		Args:  cobra.ExactArgs(1),
   106  		RunE: func(cmd *cobra.Command, args []string) error {
   107  			inBuf := bufio.NewReader(cmd.InOrStdin())
   108  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   109  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   110  
   111  			deployer := cliCtx.GetFromAddress()
   112  
   113  			contract := args[0]
   114  			if err := types.ValidateNonZeroAddress(contract); err != nil {
   115  				return fmt.Errorf("invalid contract hex address %w", err)
   116  			}
   117  
   118  			msg := &types.MsgCancelFeeSplit{
   119  				ContractAddress: contract,
   120  				DeployerAddress: deployer.String(),
   121  			}
   122  
   123  			if err := msg.ValidateBasic(); err != nil {
   124  				return err
   125  			}
   126  
   127  			return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
   128  		},
   129  	}
   130  
   131  	return cmd
   132  }
   133  
   134  // GetUpdateFeeSplit returns a CLI command handler for updating the withdraw
   135  // address of a contract for fee distribution
   136  func GetUpdateFeeSplit(cdc *codec.Codec) *cobra.Command {
   137  	cmd := &cobra.Command{
   138  		Use:   "update [contract_hex] [withdraw_bech32]",
   139  		Short: "Update withdraw address for a contract registered for fee distribution.",
   140  		Long:  "Update withdraw address for a contract registered for fee distribution. \nOnly the contract deployer can update the withdraw address.",
   141  		Args:  cobra.ExactArgs(2),
   142  		RunE: func(cmd *cobra.Command, args []string) error {
   143  			inBuf := bufio.NewReader(cmd.InOrStdin())
   144  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   145  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   146  
   147  			deployer := cliCtx.GetFromAddress()
   148  
   149  			contract := args[0]
   150  			if err := types.ValidateNonZeroAddress(contract); err != nil {
   151  				return fmt.Errorf("invalid contract hex address %w", err)
   152  			}
   153  
   154  			withdraw := args[1]
   155  			if _, err := sdk.AccAddressFromBech32(withdraw); err != nil {
   156  				return fmt.Errorf("invalid withdraw bech32 address %w", err)
   157  			}
   158  
   159  			msg := &types.MsgUpdateFeeSplit{
   160  				ContractAddress:   contract,
   161  				DeployerAddress:   deployer.String(),
   162  				WithdrawerAddress: withdraw,
   163  			}
   164  
   165  			if err := msg.ValidateBasic(); err != nil {
   166  				return err
   167  			}
   168  
   169  			return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
   170  		},
   171  	}
   172  
   173  	return cmd
   174  }
   175  
   176  // GetCmdFeeSplitSharesProposal implements a command handler for submitting a fee split change proposal transaction
   177  func GetCmdFeeSplitSharesProposal(cdcP *codec.CodecProxy, reg interfacetypes.InterfaceRegistry) *cobra.Command {
   178  	cmd := &cobra.Command{
   179  		Use:   "fee-split-shares [proposal-file]",
   180  		Args:  cobra.ExactArgs(1),
   181  		Short: "Submit a fee split shares proposal",
   182  		Long: strings.TrimSpace(
   183  			fmt.Sprintf(`Submit a fee split shares proposal along with an initial deposit.
   184  The proposal details must be supplied via a JSON file.
   185  
   186  Example:
   187  $ %s tx gov submit-proposal fee-split-shares <path/to/proposal.json> --from=<key_or_address>
   188  
   189  Where proposal.json contains:
   190  
   191  {
   192    "title": "Update the fee split shares for contract",
   193    "description": "Update the fee split shares",
   194    "shares": [
   195      {
   196        "contract_addr": "0x0d021d10ab9E155Fc1e8705d12b73f9bd3de0a36",
   197        "share": "0.5"
   198      }
   199    ],
   200    "deposit": [
   201      {
   202        "denom": "%s",
   203        "amount": "10000"
   204      }
   205    ]
   206  }
   207  `,
   208  				version.ClientName, sdk.DefaultBondDenom,
   209  			),
   210  		),
   211  		RunE: func(cmd *cobra.Command, args []string) error {
   212  			cdc := cdcP.GetCdc()
   213  			inBuf := bufio.NewReader(cmd.InOrStdin())
   214  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   215  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   216  
   217  			proposal, err := fsutils.ParseFeeSplitSharesProposalJSON(cdc, args[0])
   218  			if err != nil {
   219  				return err
   220  			}
   221  
   222  			from := cliCtx.GetFromAddress()
   223  			content := types.NewFeeSplitSharesProposal(
   224  				proposal.Title,
   225  				proposal.Description,
   226  				proposal.Shares,
   227  			)
   228  
   229  			msg := govTypes.NewMsgSubmitProposal(content, proposal.Deposit, from)
   230  			if err := msg.ValidateBasic(); err != nil {
   231  				return err
   232  			}
   233  
   234  			return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
   235  		},
   236  	}
   237  
   238  	return cmd
   239  }