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

     1  package cli
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     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  	bank "github.com/Finschia/finschia-sdk/x/bank/types"
    15  	"github.com/Finschia/finschia-sdk/x/fswap/types"
    16  )
    17  
    18  const (
    19  	FlagFromDenom           = "from-denom"
    20  	FlagToDenom             = "to-denom"
    21  	FlagAmountCapForToDenom = "to-coin-amount-cap"
    22  	FlagSwapRate            = "swap-rate"
    23  )
    24  
    25  // GetTxCmd returns the transaction commands for this module
    26  func GetTxCmd() *cobra.Command {
    27  	cmd := &cobra.Command{
    28  		Use:                        types.ModuleName,
    29  		Short:                      fmt.Sprintf("%s transactions subcommands", types.ModuleName),
    30  		DisableFlagParsing:         true,
    31  		SuggestionsMinimumDistance: 2,
    32  		RunE:                       client.ValidateCmd,
    33  	}
    34  	cmd.AddCommand(
    35  		CmdTxMsgSwap(),
    36  		CmdTxMsgSwapAll(),
    37  		CmdMsgSetSwap(),
    38  	)
    39  
    40  	return cmd
    41  }
    42  
    43  func CmdTxMsgSwap() *cobra.Command {
    44  	cmd := &cobra.Command{
    45  		Use:   "swap [from] [from_coin_amount] [to_denom]",
    46  		Short: "swap amount of from-coin to to-coin",
    47  		Args:  cobra.ExactArgs(3),
    48  		RunE: func(cmd *cobra.Command, args []string) error {
    49  			from := args[0]
    50  			if err := cmd.Flags().Set(flags.FlagFrom, from); err != nil {
    51  				return err
    52  			}
    53  
    54  			clientCtx, err := client.GetClientTxContext(cmd)
    55  			if err != nil {
    56  				return err
    57  			}
    58  
    59  			amount, err := sdk.ParseCoinNormalized(args[1])
    60  			if err != nil {
    61  				return err
    62  			}
    63  
    64  			toDenom := args[2]
    65  
    66  			msg := &types.MsgSwap{
    67  				FromAddress:    from,
    68  				FromCoinAmount: amount,
    69  				ToDenom:        toDenom,
    70  			}
    71  			if err := msg.ValidateBasic(); err != nil {
    72  				return err
    73  			}
    74  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
    75  		},
    76  	}
    77  
    78  	flags.AddTxFlagsToCmd(cmd)
    79  	return cmd
    80  }
    81  
    82  func CmdTxMsgSwapAll() *cobra.Command {
    83  	cmd := &cobra.Command{
    84  		Use:   "swap-all [from_address] [from_denom] [to_denom]",
    85  		Short: "swap all the from-coin to to-coin",
    86  		Args:  cobra.ExactArgs(3),
    87  		RunE: func(cmd *cobra.Command, args []string) error {
    88  			from := args[0]
    89  			if err := cmd.Flags().Set(flags.FlagFrom, from); err != nil {
    90  				return err
    91  			}
    92  
    93  			clientCtx, err := client.GetClientTxContext(cmd)
    94  			if err != nil {
    95  				return err
    96  			}
    97  
    98  			fromDenom := args[1]
    99  			toDenom := args[2]
   100  			msg := &types.MsgSwapAll{
   101  				FromAddress: clientCtx.GetFromAddress().String(),
   102  				FromDenom:   fromDenom,
   103  				ToDenom:     toDenom,
   104  			}
   105  			if err := msg.ValidateBasic(); err != nil {
   106  				return err
   107  			}
   108  
   109  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
   110  		},
   111  	}
   112  
   113  	flags.AddTxFlagsToCmd(cmd)
   114  	return cmd
   115  }
   116  
   117  // CmdMsgSetSwap implements a command handler for submitting a swap init proposal transaction.
   118  func CmdMsgSetSwap() *cobra.Command {
   119  	cmd := &cobra.Command{
   120  		Use:   "set-swap [authority] [metadata-json]",
   121  		Args:  cobra.ExactArgs(2),
   122  		Short: "Set a swap",
   123  		Long: `
   124  Parameters:
   125      metadata-json: messages in json format that will be executed if the proposal is accepted.
   126  
   127  Example of the content of metadata-json:
   128  
   129  {
   130    "metadata": {
   131      "description": "example of to-denom is finschia cony",
   132      "denom_units": [
   133        {
   134          "denom": "cony",
   135          "exponent": 0,
   136          "aliases": [
   137            "microfinschia"
   138          ]
   139        },
   140        {
   141          "denom": "finschia",
   142          "exponent": 6,
   143          "aliases": []
   144        }
   145      ],
   146      "base": "cony",
   147      "display": "finschia",
   148      "name": "FINSCHIA",
   149      "symbol": "FNSA"
   150    }
   151  }
   152  `,
   153  		RunE: func(cmd *cobra.Command, args []string) error {
   154  			if err := validateGenerateOnly(cmd); err != nil {
   155  				return err
   156  			}
   157  
   158  			clientCtx, err := client.GetClientTxContext(cmd)
   159  			if err != nil {
   160  				return err
   161  			}
   162  
   163  			fromDenom, err := cmd.Flags().GetString(FlagFromDenom)
   164  			if err != nil {
   165  				return err
   166  			}
   167  
   168  			toDenom, err := cmd.Flags().GetString(FlagToDenom)
   169  			if err != nil {
   170  				return err
   171  			}
   172  
   173  			amountCapStr, err := cmd.Flags().GetString(FlagAmountCapForToDenom)
   174  			if err != nil {
   175  				return err
   176  			}
   177  
   178  			amountCap, ok := sdk.NewIntFromString(amountCapStr)
   179  			if !ok {
   180  				return sdkerrors.ErrInvalidRequest.Wrapf("failed to parse %s %s", FlagAmountCapForToDenom, amountCap.String())
   181  			}
   182  
   183  			swapRate, err := cmd.Flags().GetString(FlagSwapRate)
   184  			if err != nil {
   185  				return err
   186  			}
   187  			swapRateDec, err := sdk.NewDecFromStr(swapRate)
   188  			if err != nil {
   189  				return err
   190  			}
   191  			swap := types.Swap{
   192  				FromDenom:           fromDenom,
   193  				ToDenom:             toDenom,
   194  				AmountCapForToDenom: amountCap,
   195  				SwapRate:            swapRateDec,
   196  			}
   197  
   198  			authority := args[0]
   199  			toDenomMetadata, err := parseToDenomMetadata(args[1])
   200  			if err != nil {
   201  				return err
   202  			}
   203  
   204  			msg := types.MsgSetSwap{
   205  				Authority:       authority,
   206  				Swap:            swap,
   207  				ToDenomMetadata: toDenomMetadata,
   208  			}
   209  
   210  			return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg)
   211  		},
   212  	}
   213  
   214  	cmd.Flags().String(FlagFromDenom, "", "set fromDenom string, ex) cony")
   215  	cmd.Flags().String(FlagToDenom, "", "set toDenom string, ex) peb")
   216  	cmd.Flags().String(FlagAmountCapForToDenom, "0", "set integer value for limit cap for the amount to swap to to-denom, ex 1000000000")
   217  	cmd.Flags().String(FlagSwapRate, "0", "set swap rate for swap from fromDenom to toDenom, ex(rate for cony to peb)  148079656000000")
   218  
   219  	flags.AddTxFlagsToCmd(cmd)
   220  	return cmd
   221  }
   222  
   223  func validateGenerateOnly(cmd *cobra.Command) error {
   224  	generateOnly, err := cmd.Flags().GetBool(flags.FlagGenerateOnly)
   225  	if err != nil {
   226  		return err
   227  	}
   228  	if !generateOnly {
   229  		return fmt.Errorf("you must use it with the flag --%s", flags.FlagGenerateOnly)
   230  	}
   231  	return nil
   232  }
   233  
   234  func parseToDenomMetadata(jsonDenomMetadata string) (bank.Metadata, error) {
   235  	type toDenomMeta struct {
   236  		Metadata bank.Metadata `json:"metadata"`
   237  	}
   238  	denomMeta := toDenomMeta{}
   239  	if err := json.Unmarshal([]byte(jsonDenomMetadata), &denomMeta); err != nil {
   240  		return bank.Metadata{}, err
   241  	}
   242  
   243  	if err := denomMeta.Metadata.Validate(); err != nil {
   244  		return bank.Metadata{}, err
   245  	}
   246  
   247  	return denomMeta.Metadata, nil
   248  }