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

     1  package cli
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	interfacetypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec/types"
     7  	"strings"
     8  
     9  	client "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/flags"
    10  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/version"
    11  	"github.com/fibonacci-chain/fbc/x/gov"
    12  
    13  	"github.com/pkg/errors"
    14  
    15  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/context"
    16  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    17  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    18  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth"
    19  	authTypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth"
    20  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/client/utils"
    21  	"github.com/fibonacci-chain/fbc/x/common"
    22  	dexUtils "github.com/fibonacci-chain/fbc/x/dex/client/utils"
    23  	"github.com/fibonacci-chain/fbc/x/dex/types"
    24  	"github.com/spf13/cobra"
    25  )
    26  
    27  // Dex tags
    28  const (
    29  	FlagBaseAsset          = "base-asset"
    30  	FlagQuoteAsset         = "quote-asset"
    31  	FlagInitPrice          = "init-price"
    32  	FlagProduct            = "product"
    33  	FlagFrom               = "from"
    34  	FlagTo                 = "to"
    35  	FlagWebsite            = "website"
    36  	FlagHandlingFeeAddress = "handling-fee-address"
    37  )
    38  
    39  // GetTxCmd returns the transaction commands for this module
    40  func GetTxCmd(cdc *codec.Codec) *cobra.Command {
    41  	txCmd := &cobra.Command{
    42  		Use:   "dex",
    43  		Short: "Decentralized exchange management subcommands",
    44  	}
    45  
    46  	txCmd.AddCommand(client.PostCommands(
    47  		getCmdList(cdc),
    48  		getCmdDeposit(cdc),
    49  		getCmdWithdraw(cdc),
    50  		getCmdTransferOwnership(cdc),
    51  		getCmdConfirmOwnership(cdc),
    52  		getCmdRegisterOperator(cdc),
    53  		getCmdEditOperator(cdc),
    54  	)...)
    55  
    56  	return txCmd
    57  }
    58  
    59  func getCmdList(cdc *codec.Codec) *cobra.Command {
    60  
    61  	cmd := &cobra.Command{
    62  		Use:   "list",
    63  		Short: "list a trading pair",
    64  		Args:  cobra.ExactArgs(0),
    65  		Long: strings.TrimSpace(`List a trading pair:
    66  
    67  $ fbchaincli tx dex list --base-asset mytoken --quote-asset fibo --from mykey
    68  `),
    69  		RunE: func(cmd *cobra.Command, _ []string) error {
    70  			cliCtx := context.NewCLIContext().WithCodec(cdc)
    71  
    72  			inBuf := bufio.NewReader(cmd.InOrStdin())
    73  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
    74  			if err := auth.NewAccountRetriever(cliCtx).EnsureExists(cliCtx.FromAddress); err != nil {
    75  				return err
    76  			}
    77  
    78  			flags := cmd.Flags()
    79  			baseAsset, err := flags.GetString(FlagBaseAsset)
    80  			if err != nil {
    81  				return err
    82  			}
    83  			if len(baseAsset) == 0 {
    84  				return errors.New("failed. empty base asset")
    85  			}
    86  			quoteAsset, err := flags.GetString(FlagQuoteAsset)
    87  			if err != nil {
    88  				return err
    89  			}
    90  			strInitPrice, err := flags.GetString(FlagInitPrice)
    91  			if err != nil {
    92  				return err
    93  			}
    94  			initPrice := sdk.MustNewDecFromStr(strInitPrice)
    95  			owner := cliCtx.GetFromAddress()
    96  			listMsg := types.NewMsgList(owner, baseAsset, quoteAsset, initPrice)
    97  			return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{listMsg})
    98  		},
    99  	}
   100  
   101  	cmd.Flags().StringP(FlagBaseAsset, "", "", FlagBaseAsset+" should be issued before listed to opendex")
   102  	cmd.Flags().StringP(FlagQuoteAsset, "", common.NativeToken, FlagQuoteAsset+" should be issued before listed to opendex")
   103  	cmd.Flags().StringP(FlagInitPrice, "", "0.01", FlagInitPrice+" should be valid price")
   104  
   105  	return cmd
   106  }
   107  
   108  // getCmdDeposit implements depositing tokens for a product.
   109  func getCmdDeposit(cdc *codec.Codec) *cobra.Command {
   110  	return &cobra.Command{
   111  		Use:   "deposit [product] [amount]",
   112  		Args:  cobra.ExactArgs(2),
   113  		Short: "deposit an amount of token on a product",
   114  		Long: strings.TrimSpace(`Deposit an amount of token on a product:
   115  
   116  $ fbchaincli tx dex deposit mytoken_fibo 1000fibo --from mykey
   117  
   118  The 'product' is a trading pair in full name of the tokens: ${base-asset-symbol}_${quote-asset-symbol}, for example 'mytoken_fibo'.
   119  `),
   120  		RunE: func(cmd *cobra.Command, args []string) error {
   121  			inBuf := bufio.NewReader(cmd.InOrStdin())
   122  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   123  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   124  
   125  			product := args[0]
   126  
   127  			// Get depositor address
   128  			from := cliCtx.GetFromAddress()
   129  
   130  			// Get amount of coins
   131  			amount, err := sdk.ParseDecCoin(args[1])
   132  			if err != nil {
   133  				return err
   134  			}
   135  
   136  			msg := types.NewMsgDeposit(product, amount, from)
   137  			return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
   138  		},
   139  	}
   140  }
   141  
   142  // getCmdWithdraw implements withdrawing tokens from a product.
   143  func getCmdWithdraw(cdc *codec.Codec) *cobra.Command {
   144  	return &cobra.Command{
   145  		Use:   "withdraw [product] [amount]",
   146  		Args:  cobra.ExactArgs(2),
   147  		Short: "withdraw an amount of token from a product",
   148  		Long: strings.TrimSpace(`Withdraw an amount of token from a product:
   149  
   150  $ fbchaincli tx dex withdraw mytoken_fibo 1000fibo --from mykey
   151  
   152  The 'product' is a trading pair in full name of the tokens: ${base-asset-symbol}_${quote-asset-symbol}, for example 'mytoken_fibo'.
   153  `),
   154  		RunE: func(cmd *cobra.Command, args []string) error {
   155  			inBuf := bufio.NewReader(cmd.InOrStdin())
   156  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   157  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   158  
   159  			product := args[0]
   160  
   161  			// Get depositor address
   162  			from := cliCtx.GetFromAddress()
   163  
   164  			// Get amount of coins
   165  			amount, err := sdk.ParseDecCoin(args[1])
   166  			if err != nil {
   167  				return err
   168  			}
   169  			msg := types.NewMsgWithdraw(product, amount, from)
   170  			return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
   171  		},
   172  	}
   173  }
   174  
   175  // getCmdTransferOwnership is the CLI command for transfer ownership of product
   176  func getCmdTransferOwnership(cdc *codec.Codec) *cobra.Command {
   177  	cmd := &cobra.Command{
   178  		Use:   "transfer-ownership",
   179  		Short: "change the owner of the product",
   180  		RunE: func(cmd *cobra.Command, _ []string) error {
   181  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   182  			inBuf := bufio.NewReader(cmd.InOrStdin())
   183  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   184  			if err := authTypes.NewAccountRetriever(cliCtx).EnsureExists(cliCtx.FromAddress); err != nil {
   185  				return err
   186  			}
   187  			flags := cmd.Flags()
   188  
   189  			product, err := flags.GetString(FlagProduct)
   190  			if err != nil || product == "" {
   191  				return fmt.Errorf("invalid product:%s", product)
   192  			}
   193  
   194  			to, err := flags.GetString(FlagTo)
   195  			if err != nil {
   196  				return fmt.Errorf("invalid to:%s", to)
   197  			}
   198  
   199  			toAddr, err := sdk.AccAddressFromBech32(to)
   200  			if err != nil {
   201  				return fmt.Errorf("invalid to:%s", to)
   202  			}
   203  
   204  			from := cliCtx.GetFromAddress()
   205  			msg := types.NewMsgTransferOwnership(from, toAddr, product)
   206  			return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
   207  		},
   208  	}
   209  	cmd.Flags().StringP(FlagProduct, "p", "", "product to be transferred")
   210  	cmd.Flags().String(FlagTo, "", "the user to be transferred")
   211  	return cmd
   212  }
   213  
   214  func getCmdConfirmOwnership(cdc *codec.Codec) *cobra.Command {
   215  	cmd := &cobra.Command{
   216  		Use:   "confirm-ownership",
   217  		Short: "confirm the transfer-ownership of the product",
   218  		RunE: func(cmd *cobra.Command, args []string) error {
   219  
   220  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   221  			inBuf := bufio.NewReader(cmd.InOrStdin())
   222  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   223  			if err := authTypes.NewAccountRetriever(cliCtx).EnsureExists(cliCtx.FromAddress); err != nil {
   224  				return err
   225  			}
   226  			flags := cmd.Flags()
   227  
   228  			product, err := flags.GetString(FlagProduct)
   229  			if err != nil {
   230  				return errors.New("invalid product")
   231  			}
   232  			_, err = flags.GetString(FlagFrom)
   233  			if err != nil {
   234  				return errors.New("invalid from")
   235  			}
   236  
   237  			from := cliCtx.GetFromAddress()
   238  
   239  			msg := types.NewMsgConfirmOwnership(from, product)
   240  			return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
   241  		},
   242  	}
   243  	cmd.Flags().StringP(FlagProduct, "p", "", "product to be transferred")
   244  	return cmd
   245  }
   246  
   247  // GetCmdSubmitDelistProposal implememts a command handler for submitting a dex delist proposal transaction
   248  func GetCmdSubmitDelistProposal(cdcP *codec.CodecProxy, reg interfacetypes.InterfaceRegistry) *cobra.Command {
   249  	return &cobra.Command{
   250  		Use:   "delist-proposal [proposal-file]",
   251  		Args:  cobra.ExactArgs(1),
   252  		Short: "Submit a dex delist proposal",
   253  		Long: strings.TrimSpace(
   254  			fmt.Sprintf(`Submit a dex delist proposal along with an initial deposit.
   255  The proposal details must be supplied via a JSON file.
   256  
   257  Example:
   258  $ %s tx gov submit-proposal delist-proposal <path/to/proposal.json> --from=<key_or_address>
   259  
   260  Where proposal.json contains:
   261  
   262  {
   263   "title": "delist xxx/%s",
   264   "description": "delist asset from dex",
   265   "base_asset": "xxx",
   266   "quote_asset": "%s",
   267   "deposit": [
   268     {
   269       "denom": "%s",
   270       "amount": "100"
   271     }
   272   ]
   273  }
   274  `, version.ClientName, sdk.DefaultBondDenom, sdk.DefaultBondDenom, sdk.DefaultBondDenom,
   275  			)),
   276  		RunE: func(cmd *cobra.Command, args []string) error {
   277  			cdc := cdcP.GetCdc()
   278  			inBuf := bufio.NewReader(cmd.InOrStdin())
   279  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   280  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   281  
   282  			proposal, err := dexUtils.ParseDelistProposalJSON(cdc, args[0])
   283  			if err != nil {
   284  				return err
   285  			}
   286  
   287  			from := cliCtx.GetFromAddress()
   288  			content := types.NewDelistProposal(proposal.Title, proposal.Description, from, proposal.BaseAsset, proposal.QuoteAsset)
   289  			msg := gov.NewMsgSubmitProposal(content, proposal.Deposit, from)
   290  			return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr, []sdk.Msg{msg})
   291  		},
   292  	}
   293  
   294  }
   295  
   296  func getCmdRegisterOperator(cdc *codec.Codec) *cobra.Command {
   297  	cmd := &cobra.Command{
   298  		Use:   "register-operator",
   299  		Short: "register a dex operator",
   300  		Args:  cobra.ExactArgs(0),
   301  		Long: strings.TrimSpace(`Register a dex operator:
   302  
   303  $ fbchaincli tx dex register-operator --website http://xxx/operator.json --handling-fee-address addr --from mykey
   304  `),
   305  		RunE: func(cmd *cobra.Command, _ []string) error {
   306  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   307  
   308  			inBuf := bufio.NewReader(cmd.InOrStdin())
   309  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   310  			if err := auth.NewAccountRetriever(cliCtx).EnsureExists(cliCtx.FromAddress); err != nil {
   311  				return err
   312  			}
   313  
   314  			flags := cmd.Flags()
   315  			website, err := flags.GetString(FlagWebsite)
   316  			if err != nil {
   317  				return err
   318  			}
   319  			feeAddrStr, err := flags.GetString(FlagHandlingFeeAddress)
   320  			if err != nil {
   321  				return err
   322  			}
   323  			feeAddr, err := sdk.AccAddressFromBech32(feeAddrStr)
   324  			if err != nil {
   325  				return sdk.ErrInvalidAddress(fmt.Sprintf("invalid address:%s", feeAddrStr))
   326  			}
   327  			owner := cliCtx.GetFromAddress()
   328  			operatorMsg := types.NewMsgCreateOperator(website, owner, feeAddr)
   329  			return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{operatorMsg})
   330  		},
   331  	}
   332  
   333  	cmd.Flags().String(FlagWebsite, "", `A valid http link to describe DEXOperator which ends with "operator.json" defined in OIP-{xxx},and its length should be less than 1024`)
   334  	cmd.Flags().String(FlagHandlingFeeAddress, "", "An address to receive fees of tokenpair's matched order")
   335  
   336  	return cmd
   337  }
   338  
   339  func getCmdEditOperator(cdc *codec.Codec) *cobra.Command {
   340  	cmd := &cobra.Command{
   341  		Use:   "edit-operator",
   342  		Short: "edit a dex operator",
   343  		Args:  cobra.ExactArgs(0),
   344  		Long: strings.TrimSpace(`Edit a dex operator:
   345  
   346  $ fbchaincli tx dex edit-operator --website http://xxx/operator.json --handling-fee-address addr --from mykey
   347  `),
   348  		RunE: func(cmd *cobra.Command, _ []string) error {
   349  			cliCtx := context.NewCLIContext().WithCodec(cdc)
   350  
   351  			inBuf := bufio.NewReader(cmd.InOrStdin())
   352  			txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(cdc))
   353  			if err := auth.NewAccountRetriever(cliCtx).EnsureExists(cliCtx.FromAddress); err != nil {
   354  				return err
   355  			}
   356  
   357  			flags := cmd.Flags()
   358  			website, err := flags.GetString(FlagWebsite)
   359  			if err != nil {
   360  				return err
   361  			}
   362  			feeAddrStr, err := flags.GetString(FlagHandlingFeeAddress)
   363  			if err != nil {
   364  				return err
   365  			}
   366  			feeAddr, err := sdk.AccAddressFromBech32(feeAddrStr)
   367  			if err != nil {
   368  				return sdk.ErrInvalidAddress(fmt.Sprintf("invalid address:%s", feeAddrStr))
   369  			}
   370  			owner := cliCtx.GetFromAddress()
   371  			operatorMsg := types.NewMsgUpdateOperator(website, owner, feeAddr)
   372  			return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{operatorMsg})
   373  		},
   374  	}
   375  
   376  	cmd.Flags().String(FlagWebsite, "", `A valid http link to describe DEXOperator which ends with "operator.json" defined in OIP-{xxx},and its length should be less than 1024`)
   377  	cmd.Flags().String(FlagHandlingFeeAddress, "", "An address to receive fees of tokenpair's matched order")
   378  
   379  	return cmd
   380  }