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 }