From f3d12333b84ee29b0780c56e8df6541914bbb641 Mon Sep 17 00:00:00 2001 From: zhangyelong Date: Wed, 17 Apr 2024 17:29:11 +0800 Subject: [PATCH 1/4] add cli impl of swap-to-erc20 --- modules/token/client/cli/flags.go | 6 ++- modules/token/client/cli/tx.go | 65 +++++++++++++++++++++++++++++++ modules/token/types/v1/token.go | 5 +++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/modules/token/client/cli/flags.go b/modules/token/client/cli/flags.go index 60d1f042..06d96734 100644 --- a/modules/token/client/cli/flags.go +++ b/modules/token/client/cli/flags.go @@ -25,6 +25,8 @@ var ( FsTransferTokenOwner = flag.NewFlagSet("", flag.ContinueOnError) FsMintToken = flag.NewFlagSet("", flag.ContinueOnError) FsSwapFeeToken = flag.NewFlagSet("", flag.ContinueOnError) + FsSwapToErc20 = flag.NewFlagSet("", flag.ContinueOnError) + FsSwapFromErc20 = flag.NewFlagSet("", flag.ContinueOnError) ) func init() { @@ -42,5 +44,7 @@ func init() { FsTransferTokenOwner.String(FlagTo, "", "The new owner") FsMintToken.String(FlagTo, "", "Address to which the token is to be minted") - FsSwapFeeToken.String(FlagTo, "", "Address to which the token is to be receiver") + FsSwapFeeToken.String(FlagTo, "", "Address to which the token is to be received") + FsSwapToErc20.String(FlagTo, "", "Address to which the token is to be received") + FsSwapFromErc20.String(FlagTo, "", "Address to which the token is to be received") } diff --git a/modules/token/client/cli/tx.go b/modules/token/client/cli/tx.go index 74d8f038..39564d39 100644 --- a/modules/token/client/cli/tx.go +++ b/modules/token/client/cli/tx.go @@ -415,3 +415,68 @@ func GetCmdSwapFeeToken() *cobra.Command { flags.AddTxFlagsToCmd(cmd) return cmd } + +// GetCmdSwapToErc20 implements the swap-to-erc20 command +func GetCmdSwapToErc20() *cobra.Command { + cmd := &cobra.Command{ + Use: "swap-to-erc20", + Long: "Swap native token to the corresponding ERC20 at 1:1.", + Example: fmt.Sprintf( + "$ %s tx token swap-to-erc20 [paid_amount]"+ + "--to=\"0x0eeb8ec40c6705b669469346ff8f9ce5cad57ed5\" "+ + "--from= "+ + "--chain-id= "+ + "--fees=", + version.AppName, + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress().String() + paidAmount, _, err := parseMainCoin(clientCtx, args[0]) + if err != nil { + return err + } + receiver, err := cmd.Flags().GetString(FlagTo) + if err != nil { + return err + } + if len(receiver) <= 0 { + // set default receiver + receiver = from + } + + msg := &v1.MsgSwapToERC20{ + Amount: paidAmount, + Sender: from, + Receiver: receiver, + } + + token, err := queryToken(clientCtx, paidAmount.Denom) + if err != nil { + return err + } + if len(token.GetContract()) <= 0 { + return fmt.Errorf("corresponding erc20 contract of %s does not exist", paidAmount.Denom) + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + var prompt = fmt.Sprintf("Swapping native token to ERC20, sender: %s, receiver: %s, contract %s, amount: %s", from, receiver, token.GetContract(), paidAmount) + + fmt.Println(prompt) + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().AddFlagSet(FsSwapToErc20) + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/modules/token/types/v1/token.go b/modules/token/types/v1/token.go index 7c849ed6..35361b5b 100644 --- a/modules/token/types/v1/token.go +++ b/modules/token/types/v1/token.go @@ -33,6 +33,7 @@ type TokenI interface { GetMaxSupply() uint64 GetMintable() bool GetOwner() sdk.AccAddress + GetContract() string ToMainCoin(coin sdk.Coin) (sdk.DecCoin, error) ToMinCoin(coin sdk.DecCoin) (sdk.Coin, error) @@ -110,6 +111,10 @@ func (t Token) GetOwner() sdk.AccAddress { return owner } +func (t Token) GetContract() string { + return t.Contract +} + // ToMainCoin returns the main denom coin from args func (t Token) ToMainCoin(coin sdk.Coin) (sdk.DecCoin, error) { if t.MinUnit != coin.Denom { From c05bda04dde27970f09a6c9d360e18c750a86e46 Mon Sep 17 00:00:00 2001 From: zhangyelong Date: Wed, 17 Apr 2024 18:04:03 +0800 Subject: [PATCH 2/4] add cli impl of swap-from-erc20 --- modules/token/client/cli/tx.go | 67 +++++++++++++++++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/modules/token/client/cli/tx.go b/modules/token/client/cli/tx.go index 39564d39..f2ab402f 100644 --- a/modules/token/client/cli/tx.go +++ b/modules/token/client/cli/tx.go @@ -467,7 +467,7 @@ func GetCmdSwapToErc20() *cobra.Command { return err } - var prompt = fmt.Sprintf("Swapping native token to ERC20, sender: %s, receiver: %s, contract %s, amount: %s", from, receiver, token.GetContract(), paidAmount) + var prompt = fmt.Sprintf("Swapping native token to ERC20, sender: %s, receiver: %s, contract: %s, amount: %s", from, receiver, token.GetContract(), paidAmount) fmt.Println(prompt) @@ -480,3 +480,68 @@ func GetCmdSwapToErc20() *cobra.Command { return cmd } + +// GetCmdSwapFromErc20 implements the swap-from-erc20 command +func GetCmdSwapFromErc20() *cobra.Command { + cmd := &cobra.Command{ + Use: "swap-from-erc20", + Long: "Swap native token from the corresponding ERC20 at 1:1.", + Example: fmt.Sprintf( + "$ %s tx token swap-from-erc20 [wanted_amount]"+ + "--to=\"iaaeeb8ec40c6705b669469346ff8f9ce5cad57ed5\" "+ + "--from= "+ + "--chain-id= "+ + "--fees=", + version.AppName, + ), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + from := clientCtx.GetFromAddress().String() + wantedAmount, _, err := parseMainCoin(clientCtx, args[0]) + if err != nil { + return err + } + receiver, err := cmd.Flags().GetString(FlagTo) + if err != nil { + return err + } + if len(receiver) <= 0 { + // set default receiver + receiver = from + } + + msg := &v1.MsgSwapFromERC20{ + WantedAmount: wantedAmount, + Sender: from, + Receiver: receiver, + } + + token, err := queryToken(clientCtx, wantedAmount.Denom) + if err != nil { + return err + } + if len(token.GetContract()) <= 0 { + return fmt.Errorf("corresponding erc20 contract of %s does not exist", wantedAmount.Denom) + } + + if err := msg.ValidateBasic(); err != nil { + return err + } + + var prompt = fmt.Sprintf("Swapping native token from ERC20, sender: %s, receiver: %s, contract: %s, amount: %s", from, receiver, token.GetContract(), wantedAmount) + + fmt.Println(prompt) + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().AddFlagSet(FsSwapFromErc20) + flags.AddTxFlagsToCmd(cmd) + + return cmd +} From bb6bbfed6689eafcae90ddc8c1b3cfa638a0e402 Mon Sep 17 00:00:00 2001 From: zhangyelong Date: Wed, 17 Apr 2024 18:14:30 +0800 Subject: [PATCH 3/4] add tests for swap to/from erc20 --- modules/token/client/cli/cli_test.go | 50 +++++++++++++++++++ modules/token/client/testutil/test_helpers.go | 32 ++++++++++++ 2 files changed, 82 insertions(+) diff --git a/modules/token/client/cli/cli_test.go b/modules/token/client/cli/cli_test.go index b0e5be3a..1e3cb389 100644 --- a/modules/token/client/cli/cli_test.go +++ b/modules/token/client/cli/cli_test.go @@ -240,4 +240,54 @@ func (s *IntegrationTestSuite) TestToken() { token3 := tokentestutil.QueryTokenExec(s.T(), s.network, clientCtx, tokenSymbol) s.Require().Equal(to, token3.GetOwner()) // --------------------------------------------------------------------------- + + //------test GetCmdSwapToErc20()------------- + args = []string{ + fmt.Sprintf("--%s=%s", tokencli.FlagTo, to.String()), + + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf( + "--%s=%s", + flags.FlagFees, + sdk.NewCoins(sdk.NewCoin(s.network.BondDenom, sdk.NewInt(10))).String(), + ), + } + + txResult = tokentestutil.SwapToERC20Exec( + s.T(), + s.network, + clientCtx, + from.String(), + sdk.NewCoins(sdk.NewCoin(s.network.BondDenom, sdk.NewInt(1))).String(), + args...) + + // TODO assert + // s.Require().Equal(expectedCode, txResult.Code) + // --------------------------------------------------------------------------- + + //------test GetCmdSwapFromErc20()------------- + args = []string{ + fmt.Sprintf("--%s=%s", tokencli.FlagTo, to.String()), + + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), + fmt.Sprintf( + "--%s=%s", + flags.FlagFees, + sdk.NewCoins(sdk.NewCoin(s.network.BondDenom, sdk.NewInt(10))).String(), + ), + } + + txResult = tokentestutil.SwapFromERC20Exec( + s.T(), + s.network, + clientCtx, + from.String(), + sdk.NewCoins(sdk.NewCoin(s.network.BondDenom, sdk.NewInt(1))).String(), + args...) + + // TODO assert + // s.Require().Equal(expectedCode, txResult.Code) + // --------------------------------------------------------------------------- } diff --git a/modules/token/client/testutil/test_helpers.go b/modules/token/client/testutil/test_helpers.go index 7fad5da6..e32d3de0 100644 --- a/modules/token/client/testutil/test_helpers.go +++ b/modules/token/client/testutil/test_helpers.go @@ -96,6 +96,38 @@ func TransferTokenOwnerExec(t *testing.T, return network.ExecTxCmdWithResult(t, clientCtx, tokencli.GetCmdTransferTokenOwner(), args) } +func SwapToERC20Exec(t *testing.T, + network simapp.Network, + clientCtx client.Context, + from string, + coinStr string, + extraArgs ...string, +) *simapp.ResponseTx { + args := []string{ + coinStr, + fmt.Sprintf("--%s=%s", flags.FlagFrom, from), + } + args = append(args, extraArgs...) + + return network.ExecTxCmdWithResult(t, clientCtx, tokencli.GetCmdSwapToErc20(), args) +} + +func SwapFromERC20Exec(t *testing.T, + network simapp.Network, + clientCtx client.Context, + from string, + coinStr string, + extraArgs ...string, +) *simapp.ResponseTx { + args := []string{ + coinStr, + fmt.Sprintf("--%s=%s", flags.FlagFrom, from), + } + args = append(args, extraArgs...) + + return network.ExecTxCmdWithResult(t, clientCtx, tokencli.GetCmdSwapFromErc20(), args) +} + func QueryTokenExec(t *testing.T, network simapp.Network, clientCtx client.Context, From b0bffe8047979c64c2f77919da4b6ced3c5b5736 Mon Sep 17 00:00:00 2001 From: zhangyelong Date: Thu, 18 Apr 2024 09:34:32 +0800 Subject: [PATCH 4/4] fix duplicate token query --- modules/token/client/cli/tx.go | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/modules/token/client/cli/tx.go b/modules/token/client/cli/tx.go index f2ab402f..a4127a05 100644 --- a/modules/token/client/cli/tx.go +++ b/modules/token/client/cli/tx.go @@ -33,6 +33,8 @@ func NewTxCmd() *cobra.Command { GetCmdBurnToken(), GetCmdTransferTokenOwner(), GetCmdSwapFeeToken(), + GetCmdSwapToErc20(), + GetCmdSwapFromErc20(), ) return txCmd @@ -436,10 +438,14 @@ func GetCmdSwapToErc20() *cobra.Command { } from := clientCtx.GetFromAddress().String() - paidAmount, _, err := parseMainCoin(clientCtx, args[0]) + paidAmount, token, err := parseMainCoin(clientCtx, args[0]) if err != nil { return err } + if len(token.GetContract()) <= 0 { + return fmt.Errorf("corresponding erc20 contract of %s does not exist", paidAmount.Denom) + } + receiver, err := cmd.Flags().GetString(FlagTo) if err != nil { return err @@ -455,14 +461,6 @@ func GetCmdSwapToErc20() *cobra.Command { Receiver: receiver, } - token, err := queryToken(clientCtx, paidAmount.Denom) - if err != nil { - return err - } - if len(token.GetContract()) <= 0 { - return fmt.Errorf("corresponding erc20 contract of %s does not exist", paidAmount.Denom) - } - if err := msg.ValidateBasic(); err != nil { return err } @@ -501,10 +499,14 @@ func GetCmdSwapFromErc20() *cobra.Command { } from := clientCtx.GetFromAddress().String() - wantedAmount, _, err := parseMainCoin(clientCtx, args[0]) + wantedAmount, token, err := parseMainCoin(clientCtx, args[0]) if err != nil { return err } + if len(token.GetContract()) <= 0 { + return fmt.Errorf("corresponding erc20 contract of %s does not exist", wantedAmount.Denom) + } + receiver, err := cmd.Flags().GetString(FlagTo) if err != nil { return err @@ -520,14 +522,6 @@ func GetCmdSwapFromErc20() *cobra.Command { Receiver: receiver, } - token, err := queryToken(clientCtx, wantedAmount.Denom) - if err != nil { - return err - } - if len(token.GetContract()) <= 0 { - return fmt.Errorf("corresponding erc20 contract of %s does not exist", wantedAmount.Denom) - } - if err := msg.ValidateBasic(); err != nil { return err }