diff --git a/CHANGELOG.md b/CHANGELOG.md index 191a1fbc021..7d0b09d3ea4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,7 +73,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Misc Improvements -* [#3611](https://github.com/osmosis-labs/osmosis/pull/3611) Introduce osmocli, to automate thousands of lines of CLI boilerplate +* [#3611](https://github.com/osmosis-labs/osmosis/pull/3611),[#3647](https://github.com/osmosis-labs/osmosis/pull/3647) Introduce osmocli, to automate thousands of lines of CLI boilerplate * [#3634](https://github.com/osmosis-labs/osmosis/pull/3634) (Makefile) Ensure correct golang version in make build and make install. (Thank you @jhernandezb ) ## v13.0.0 diff --git a/osmoutils/cli_helpers.go b/osmoutils/cli_helpers.go index 88b2a25a0dd..c9e4db9d25b 100644 --- a/osmoutils/cli_helpers.go +++ b/osmoutils/cli_helpers.go @@ -8,6 +8,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/tendermint/tendermint/crypto/ed25519" ) func DefaultFeeString(cfg network.Config) string { @@ -47,3 +48,39 @@ func ParseSdkIntFromString(s string, separator string) ([]sdk.Int, error) { } return parsedInts, nil } + +func ParseSdkDecFromString(s string, separator string) ([]sdk.Dec, error) { + var parsedDec []sdk.Dec + for _, weightStr := range strings.Split(s, separator) { + weightStr = strings.TrimSpace(weightStr) + + parsed, err := sdk.NewDecFromStr(weightStr) + if err != nil { + return parsedDec, err + } + + parsedDec = append(parsedDec, parsed) + } + return parsedDec, nil +} + +func ParseSdkValAddressFromString(s string, separator string) []sdk.ValAddress { + var parsedAddr []sdk.ValAddress + for _, addr := range strings.Split(s, separator) { + valAddr := sdk.ValAddress([]byte(addr)) + parsedAddr = append(parsedAddr, valAddr) + } + + return parsedAddr +} + +// CreateRandomAccounts is a function return a list of randomly generated AccAddresses +func CreateRandomAccounts(numAccts int) []sdk.AccAddress { + testAddrs := make([]sdk.AccAddress, numAccts) + for i := 0; i < numAccts; i++ { + pk := ed25519.GenPrivKey().PubKey() + testAddrs[i] = sdk.AccAddress(pk.Address()) + } + + return testAddrs +} diff --git a/osmoutils/osmocli/cli_tester.go b/osmoutils/osmocli/cli_tester.go new file mode 100644 index 00000000000..4ef6aaf9bdb --- /dev/null +++ b/osmoutils/osmocli/cli_tester.go @@ -0,0 +1,111 @@ +package osmocli + +import ( + "strings" + "testing" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/gogo/protobuf/proto" + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "github.com/stretchr/testify/require" +) + +type TxCliTestCase[M sdk.Msg] struct { + Cmd string + ExpectedMsg M + ExpectedErr bool + OnlyCheckValidateBasic bool +} + +type QueryCliTestCase[Q proto.Message] struct { + Cmd string + ExpectedQuery Q + ExpectedErr bool +} + +func RunTxTestCases[M sdk.Msg](t *testing.T, desc *TxCliDesc, testcases map[string]TxCliTestCase[M]) { + for name, tc := range testcases { + t.Run(name, func(t *testing.T) { + RunTxTestCase(t, desc, &tc) + }) + } +} + +func RunQueryTestCases[Q proto.Message](t *testing.T, desc *QueryDescriptor, testcases map[string]QueryCliTestCase[Q]) { + for name, tc := range testcases { + t.Run(name, func(t *testing.T) { + RunQueryTestCase(t, desc, &tc) + }) + } +} + +func RunTxTestCase[M sdk.Msg](t *testing.T, desc *TxCliDesc, tc *TxCliTestCase[M]) { + cmd := BuildTxCli[M](desc) + err := resetCommandFlagValues(cmd) + require.NoError(t, err, "error in resetCommandFlagValues") + args := strings.Split(tc.Cmd, " ") + err = cmd.Flags().Parse(args) + require.NoError(t, err, "error in cmd.Flags().Parse(args)") + clientCtx := newClientContextWithFrom(t, cmd.Flags()) + + msg, err := desc.ParseAndBuildMsg(clientCtx, args, cmd.Flags()) + if tc.ExpectedErr { + require.Error(t, err) + return + } + require.NoError(t, err, "error in desc.ParseAndBuildMsg") + if tc.OnlyCheckValidateBasic { + require.NoError(t, msg.ValidateBasic()) + return + } + + require.Equal(t, tc.ExpectedMsg, msg) +} + +func RunQueryTestCase[Q proto.Message](t *testing.T, desc *QueryDescriptor, tc *QueryCliTestCase[Q]) { + cmd := BuildQueryCli[Q, int](desc, nil) + err := resetCommandFlagValues(cmd) + require.NoError(t, err, "error in resetCommandFlagValues") + args := strings.Split(tc.Cmd, " ") + err = cmd.Flags().Parse(args) + require.NoError(t, err, "error in cmd.Flags().Parse(args)") + + req, err := desc.ParseQuery(args, cmd.Flags()) + if tc.ExpectedErr { + require.Error(t, err) + return + } + require.NoError(t, err, "error in desc.ParseQuery") + require.Equal(t, tc.ExpectedQuery, req) +} + +// This logic is copied from the SDK, it should've just been publicly exposed. +// But instead its buried within a mega-method. +func newClientContextWithFrom(t *testing.T, fs *pflag.FlagSet) client.Context { + clientCtx := client.Context{} + from, _ := fs.GetString(flags.FlagFrom) + fromAddr, fromName, _, err := client.GetFromFields(nil, from, true) + require.NoError(t, err) + + clientCtx = clientCtx.WithFrom(from).WithFromAddress(fromAddr).WithFromName(fromName) + return clientCtx +} + +// taken from https://github.com/golang/debug/pull/8, +// due to no cobra command for resetting flag value +func resetCommandFlagValues(cmd *cobra.Command) error { + var retErr error = nil + cmd.Flags().VisitAll(func(f *pflag.Flag) { + if f.Changed { + err := f.Value.Set(f.DefValue) + if err != nil { + retErr = err + } + f.Changed = false + } + }) + return retErr +} diff --git a/osmoutils/osmocli/query_cmd_wrap.go b/osmoutils/osmocli/query_cmd_wrap.go index 5515868b1f2..b1327826ca0 100644 --- a/osmoutils/osmocli/query_cmd_wrap.go +++ b/osmoutils/osmocli/query_cmd_wrap.go @@ -11,13 +11,12 @@ import ( grpc1 "github.com/gogo/protobuf/grpc" "github.com/gogo/protobuf/proto" "github.com/spf13/cobra" + "github.com/spf13/pflag" ) -func QueryIndexCmd(moduleName string) *cobra.Command { - cmd := IndexCmd(moduleName) - cmd.Short = fmt.Sprintf("Querying commands for the %s module", moduleName) - return cmd -} +// global variable set on index command. +// helps populate Longs, when not set in QueryDescriptor. +var lastQueryModuleName string type QueryDescriptor struct { Use string @@ -33,25 +32,70 @@ type QueryDescriptor struct { CustomFlagOverrides map[string]string // Map of FieldName -> CustomParseFn CustomFieldParsers map[string]CustomFieldParserFn + + ParseQuery func(args []string, flags *pflag.FlagSet) (proto.Message, error) + + ModuleName string + numArgs int } -func SimpleQueryFromDescriptor[reqP proto.Message, querier any](desc QueryDescriptor, newQueryClientFn func(grpc1.ClientConn) querier) *cobra.Command { - numArgs := ParseNumFields[reqP]() - len(desc.CustomFlagOverrides) +func QueryIndexCmd(moduleName string) *cobra.Command { + cmd := IndexCmd(moduleName) + cmd.Short = fmt.Sprintf("Querying commands for the %s module", moduleName) + lastQueryModuleName = moduleName + return cmd +} + +func AddQueryCmd[Q proto.Message, querier any](cmd *cobra.Command, newQueryClientFn func(grpc1.ClientConn) querier, f func() (*QueryDescriptor, Q)) { + desc, _ := f() + prepareDescriptor[Q](desc) + subCmd := BuildQueryCli[Q](desc, newQueryClientFn) + cmd.AddCommand(subCmd) +} + +func (desc *QueryDescriptor) FormatLong(moduleName string) { + desc.Long = FormatLongDesc(desc.Long, NewLongMetadata(moduleName).WithShort(desc.Short)) +} + +func prepareDescriptor[reqP proto.Message](desc *QueryDescriptor) { + if !desc.HasPagination { + desc.HasPagination = ParseHasPagination[reqP]() + } + if desc.QueryFnName == "" { + desc.QueryFnName = ParseExpectedQueryFnName[reqP]() + } + if strings.Contains(desc.Long, "{") { + if desc.ModuleName == "" { + desc.ModuleName = lastQueryModuleName + } + desc.FormatLong(desc.ModuleName) + } + + desc.numArgs = ParseNumFields[reqP]() - len(desc.CustomFlagOverrides) if desc.HasPagination { - numArgs = numArgs - 1 + desc.numArgs = desc.numArgs - 1 + } +} + +func BuildQueryCli[reqP proto.Message, querier any](desc *QueryDescriptor, newQueryClientFn func(grpc1.ClientConn) querier) *cobra.Command { + prepareDescriptor[reqP](desc) + if desc.ParseQuery == nil { + desc.ParseQuery = func(args []string, fs *pflag.FlagSet) (proto.Message, error) { + flagAdvice := FlagAdvice{ + HasPagination: desc.HasPagination, + CustomFlagOverrides: desc.CustomFlagOverrides, + CustomFieldParsers: desc.CustomFieldParsers, + }.Sanitize() + return ParseFieldsFromFlagsAndArgs[reqP](flagAdvice, fs, args) + } } - flagAdvice := FlagAdvice{ - HasPagination: desc.HasPagination, - CustomFlagOverrides: desc.CustomFlagOverrides, - CustomFieldParsers: desc.CustomFieldParsers, - }.Sanitize() + cmd := &cobra.Command{ Use: desc.Use, Short: desc.Short, Long: desc.Long, - Args: cobra.ExactArgs(numArgs), - RunE: NewQueryLogicAllFieldsAsArgs[reqP]( - flagAdvice, desc.QueryFnName, newQueryClientFn), + Args: cobra.ExactArgs(desc.numArgs), + RunE: queryLogic(desc, newQueryClientFn), } flags.AddQueryFlagsToCmd(cmd) AddFlags(cmd, desc.Flags) @@ -70,25 +114,23 @@ func SimpleQueryFromDescriptor[reqP proto.Message, querier any](desc QueryDescri func SimpleQueryCmd[reqP proto.Message, querier any](use string, short string, long string, moduleName string, newQueryClientFn func(grpc1.ClientConn) querier) *cobra.Command { desc := QueryDescriptor{ - Use: use, - Short: short, - Long: FormatLongDesc(long, NewLongMetadata(moduleName).WithShort(short)), - HasPagination: ParseHasPagination[reqP](), - QueryFnName: ParseExpectedQueryFnName[reqP](), + Use: use, + Short: short, + Long: FormatLongDesc(long, NewLongMetadata(moduleName).WithShort(short)), } - return SimpleQueryFromDescriptor[reqP](desc, newQueryClientFn) + return BuildQueryCli[reqP](&desc, newQueryClientFn) } func GetParams[reqP proto.Message, querier any](moduleName string, newQueryClientFn func(grpc1.ClientConn) querier) *cobra.Command { - return SimpleQueryFromDescriptor[reqP](QueryDescriptor{ + return BuildQueryCli[reqP](&QueryDescriptor{ Use: "params [flags]", Short: fmt.Sprintf("Get the params for the x/%s module", moduleName), QueryFnName: "Params", }, newQueryClientFn) } -func callQueryClientFn[reqP proto.Message, querier any](ctx context.Context, fnName string, req reqP, q querier) (res proto.Message, err error) { +func callQueryClientFn(ctx context.Context, fnName string, req proto.Message, q any) (res proto.Message, err error) { qVal := reflect.ValueOf(q) method := qVal.MethodByName(fnName) args := []reflect.Value{ @@ -109,7 +151,7 @@ func callQueryClientFn[reqP proto.Message, querier any](ctx context.Context, fnN return res, nil } -func NewQueryLogicAllFieldsAsArgs[reqP proto.Message, querier any](flagAdvice FlagAdvice, keeperFnName string, +func queryLogic[querier any](desc *QueryDescriptor, newQueryClientFn func(grpc1.ClientConn) querier) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientQueryContext(cmd) @@ -117,14 +159,13 @@ func NewQueryLogicAllFieldsAsArgs[reqP proto.Message, querier any](flagAdvice Fl return err } queryClient := newQueryClientFn(clientCtx) - var req reqP - req, err = ParseFieldsFromFlagsAndArgs[reqP](flagAdvice, cmd.Flags(), args) + req, err := desc.ParseQuery(args, cmd.Flags()) if err != nil { return err } - res, err := callQueryClientFn(cmd.Context(), keeperFnName, req, queryClient) + res, err := callQueryClientFn(cmd.Context(), desc.QueryFnName, req, queryClient) if err != nil { return err } diff --git a/osmoutils/osmocli/tx_cmd_wrap.go b/osmoutils/osmocli/tx_cmd_wrap.go index 7c2096cb289..48725fe9e30 100644 --- a/osmoutils/osmocli/tx_cmd_wrap.go +++ b/osmoutils/osmocli/tx_cmd_wrap.go @@ -36,21 +36,29 @@ type TxCliDesc struct { CustomFieldParsers map[string]CustomFieldParserFn } +func AddTxCmd[M sdk.Msg](cmd *cobra.Command, f func() (*TxCliDesc, M)) { + desc, _ := f() + subCmd := BuildTxCli[M](desc) + cmd.AddCommand(subCmd) +} + func BuildTxCli[M sdk.Msg](desc *TxCliDesc) *cobra.Command { desc.TxSignerFieldName = strings.ToLower(desc.TxSignerFieldName) if desc.NumArgs == 0 { // NumArgs = NumFields - 1, since 1 field is from the msg desc.NumArgs = ParseNumFields[M]() - 1 - len(desc.CustomFlagOverrides) - len(desc.CustomFieldParsers) } - desc.ParseAndBuildMsg = func(clientCtx client.Context, args []string, flags *pflag.FlagSet) (sdk.Msg, error) { - flagAdvice := FlagAdvice{ - IsTx: true, - TxSenderFieldName: desc.TxSignerFieldName, - FromValue: clientCtx.GetFromAddress().String(), - CustomFlagOverrides: desc.CustomFlagOverrides, - CustomFieldParsers: desc.CustomFieldParsers, - }.Sanitize() - return ParseFieldsFromFlagsAndArgs[M](flagAdvice, flags, args) + if desc.ParseAndBuildMsg == nil { + desc.ParseAndBuildMsg = func(clientCtx client.Context, args []string, flags *pflag.FlagSet) (sdk.Msg, error) { + flagAdvice := FlagAdvice{ + IsTx: true, + TxSenderFieldName: desc.TxSignerFieldName, + FromValue: clientCtx.GetFromAddress().String(), + CustomFlagOverrides: desc.CustomFlagOverrides, + CustomFieldParsers: desc.CustomFieldParsers, + }.Sanitize() + return ParseFieldsFromFlagsAndArgs[M](flagAdvice, flags, args) + } } return desc.BuildCommandCustomFn() } diff --git a/x/gamm/client/cli/cli_test.go b/x/gamm/client/cli/cli_test.go index 8958d2c578a..d1795fca9dc 100644 --- a/x/gamm/client/cli/cli_test.go +++ b/x/gamm/client/cli/cli_test.go @@ -4,27 +4,22 @@ import ( "fmt" "testing" - "github.com/gogo/protobuf/proto" "github.com/stretchr/testify/suite" - "github.com/osmosis-labs/osmosis/v13/app" "github.com/osmosis-labs/osmosis/v13/osmoutils" + "github.com/osmosis-labs/osmosis/v13/osmoutils/osmocli" "github.com/osmosis-labs/osmosis/v13/x/gamm/client/cli" - gammtestutil "github.com/osmosis-labs/osmosis/v13/x/gamm/client/testutil" + "github.com/osmosis-labs/osmosis/v13/x/gamm/pool-models/balancer" "github.com/osmosis-labs/osmosis/v13/x/gamm/types" - gammtypes "github.com/osmosis-labs/osmosis/v13/x/gamm/types" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/crypto/hd" - "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/testutil" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" - banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" - tmcli "github.com/tendermint/tendermint/libs/cli" + "github.com/cosmos/cosmos-sdk/types/query" ) +var testAddresses = osmoutils.CreateRandomAccounts(3) + type IntegrationTestSuite struct { suite.Suite @@ -32,115 +27,21 @@ type IntegrationTestSuite struct { network *network.Network } -func (s *IntegrationTestSuite) SetupSuite() { - s.T().Log("setting up integration test suite") - - s.cfg = app.DefaultConfig() - - // modification to pay fee with test bond denom "stake" - genesisState := app.ModuleBasics.DefaultGenesis(s.cfg.Codec) - gammGen := gammtypes.DefaultGenesis() - gammGen.Params.PoolCreationFee = sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 1000000)} - gammGenJson := s.cfg.Codec.MustMarshalJSON(gammGen) - genesisState[gammtypes.ModuleName] = gammGenJson - s.cfg.GenesisState = genesisState - - s.network = network.New(s.T(), s.cfg) - - _, err := s.network.WaitForHeight(1) - s.Require().NoError(err) - - val := s.network.Validators[0] - - // create a new pool - _, err = gammtestutil.MsgCreatePool(s.T(), val.ClientCtx, val.Address, "5stake,5node0token", "100stake,100node0token", "0.01", "0.01", "") - s.Require().NoError(err) - - _, err = s.network.WaitForHeight(1) - s.Require().NoError(err) -} - -func (s *IntegrationTestSuite) TearDownSuite() { - s.T().Log("tearing down integration test suite") - s.network.Cleanup() -} - -func (s *IntegrationTestSuite) TestNewCreatePoolCmd() { - val := s.network.Validators[0] - - info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewCreatePoolAddr", - keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) - s.Require().NoError(err) - - newAddr := sdk.AccAddress(info.GetPubKey().Address()) - - _, err = banktestutil.MsgSendExec( - val.ClientCtx, - val.Address, - newAddr, - sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 200000000), sdk.NewInt64Coin("node0token", 20000)), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - osmoutils.DefaultFeeString(s.cfg), - ) - s.Require().NoError(err) - - testCases := []struct { - name string - json string - expectErr bool - respType proto.Message - expectedCode uint32 +func TestNewCreatePoolCmd(t *testing.T) { + testCases := map[string]struct { + json string + expectErr bool }{ - { - "one token pair pool", - fmt.Sprintf(` - { - "%s": "1node0token", - "%s": "100node0token", - "%s": "0.001", - "%s": "0.001" - } - `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee), - true, &sdk.TxResponse{}, 4, - }, - { - "two tokens pair pool", - fmt.Sprintf(` - { - "%s": "1node0token,3stake", - "%s": "100node0token,100stake", - "%s": "0.001", - "%s": "0.001" - } - `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee), - false, &sdk.TxResponse{}, 0, - }, - { - "change order of json fields", - fmt.Sprintf(` - { - "%s": "100node0token,100stake", - "%s": "0.001", - "%s": "1node0token,3stake", - "%s": "0.001" - } - `, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileWeights, cli.PoolFileExitFee), - false, &sdk.TxResponse{}, 0, - }, - { // --record-tokens=100.0stake2 --record-tokens=100.0stake --record-tokens-weight=5 --record-tokens-weight=5 --swap-fee=0.01 --exit-fee=0.01 --from=validator --keyring-backend=test --chain-id=testing --yes - "three tokens pair pool - insufficient balance check", - fmt.Sprintf(` - { - "%s": "1node0token,1stake,2btc", - "%s": "100node0token,100stake,100btc", - "%s": "0.001", - "%s": "0.001" - } - `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee), - false, &sdk.TxResponse{}, 5, + "two tokens pair pool": { + `{ + "weights": "1node0token,3stake", + "initial-deposit": "100node0token,100stake", + "swap-fee": "0.001", + "exit-fee": "0.001" + }`, + false, }, - { - "future governor address", + "future governor address": { fmt.Sprintf(` { "%s": "1node0token,3stake", @@ -150,56 +51,9 @@ func (s *IntegrationTestSuite) TestNewCreatePoolCmd() { "%s": "osmo1fqlr98d45v5ysqgp6h56kpujcj4cvsjnjq9nck" } `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee, cli.PoolFileFutureGovernor), - false, &sdk.TxResponse{}, 0, - }, - // Due to CI time concerns, we leave these CLI tests commented out, and instead guaranteed via - // the logic tests. - // { - // "future governor time", - // fmt.Sprintf(` - // { - // "%s": "1node0token,3stake", - // "%s": "100node0token,100stake", - // "%s": "0.001", - // "%s": "0.001", - // "%s": "2h" - // } - // `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee, cli.PoolFileFutureGovernor), - // false, &sdk.TxResponse{}, 0, - // }, - // { - // "future governor token + time", - // fmt.Sprintf(` - // { - // "%s": "1node0token,3stake", - // "%s": "100node0token,100stake", - // "%s": "0.001", - // "%s": "0.001", - // "%s": "token,1000h" - // } - // `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee, cli.PoolFileFutureGovernor), - // false, &sdk.TxResponse{}, 0, - // }, - // { - // "invalid future governor", - // fmt.Sprintf(` - // { - // "%s": "1node0token,3stake", - // "%s": "100node0token,100stake", - // "%s": "0.001", - // "%s": "0.001", - // "%s": "validdenom,invalidtime" - // } - // `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee, cli.PoolFileFutureGovernor), - // true, &sdk.TxResponse{}, 7, - // }, - { - "not valid json", - "bad json", - true, &sdk.TxResponse{}, 0, + false, }, - { - "bad pool json - missing quotes around exit fee", + "bad pool json - missing quotes around exit fee": { fmt.Sprintf(` { "%s": "1node0token,3stake", @@ -208,14 +62,12 @@ func (s *IntegrationTestSuite) TestNewCreatePoolCmd() { "%s": 0.001 } `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee), - true, &sdk.TxResponse{}, 0, + true, }, - { - "empty pool json", - "", true, &sdk.TxResponse{}, 0, + "empty pool json": { + "", true, }, - { - "smooth change params", + "smooth change params": { fmt.Sprintf(` { "%s": "1node0token,3stake", @@ -231,10 +83,9 @@ func (s *IntegrationTestSuite) TestNewCreatePoolCmd() { `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee, cli.PoolFileSmoothWeightChangeParams, cli.PoolFileDuration, cli.PoolFileTargetPoolWeights, cli.PoolFileStartTime, ), - false, &sdk.TxResponse{}, 0, + false, }, - { - "smooth change params - no start time", + "smooth change params - no start time": { fmt.Sprintf(` { "%s": "1node0token,3stake", @@ -249,10 +100,9 @@ func (s *IntegrationTestSuite) TestNewCreatePoolCmd() { `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee, cli.PoolFileSmoothWeightChangeParams, cli.PoolFileDuration, cli.PoolFileTargetPoolWeights, ), - false, &sdk.TxResponse{}, 0, + false, }, - { - "empty smooth change params", + "empty smooth change params": { fmt.Sprintf(` { "%s": "1node0token,3stake", @@ -264,10 +114,9 @@ func (s *IntegrationTestSuite) TestNewCreatePoolCmd() { `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee, cli.PoolFileSmoothWeightChangeParams, ), - false, &sdk.TxResponse{}, 0, + false, }, - { - "smooth change params wrong type", + "smooth change params wrong type": { fmt.Sprintf(` { "%s": "1node0token,3stake", @@ -279,10 +128,9 @@ func (s *IntegrationTestSuite) TestNewCreatePoolCmd() { `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee, cli.PoolFileSmoothWeightChangeParams, ), - true, &sdk.TxResponse{}, 0, + true, }, - { - "smooth change params missing duration", + "smooth change params missing duration": { fmt.Sprintf(` { "%s": "1node0token,3stake", @@ -296,10 +144,9 @@ func (s *IntegrationTestSuite) TestNewCreatePoolCmd() { `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee, cli.PoolFileSmoothWeightChangeParams, cli.PoolFileTargetPoolWeights, ), - true, &sdk.TxResponse{}, 0, + true, }, - { - "unknown fields in json", + "unknown fields in json": { fmt.Sprintf(` { "%s": "1node0token", @@ -309,831 +156,223 @@ func (s *IntegrationTestSuite) TestNewCreatePoolCmd() { "unknown": true, } `, cli.PoolFileWeights, cli.PoolFileInitialDeposit, cli.PoolFileSwapFee, cli.PoolFileExitFee), - true, &sdk.TxResponse{}, 0, + true, }, } - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewCreatePoolCmd() - clientCtx := val.ClientCtx + for name, tc := range testCases { + t.Run(name, func(tt *testing.T) { + desc := cli.NewCreatePoolCmd() + jsonFile := testutil.WriteToNewTempFile(tt, tc.json) + Cmd := fmt.Sprintf("--pool-file=%s --from=%s", jsonFile.Name(), testAddresses[0].String()) - jsonFile := testutil.WriteToNewTempFile(s.T(), tc.json) - - args := []string{ - fmt.Sprintf("--%s=%s", cli.FlagPoolFile, jsonFile.Name()), - fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - osmoutils.DefaultFeeString(s.cfg), - fmt.Sprintf("--%s=%s", flags.FlagGas, fmt.Sprint(300000)), - } - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - err = clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType) - s.Require().NoError(err, out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + txTc := osmocli.TxCliTestCase[*balancer.MsgCreateBalancerPool]{ + Cmd: Cmd, + ExpectedErr: tc.expectErr, + OnlyCheckValidateBasic: true, } + osmocli.RunTxTestCase(tt, desc, &txTc) }) } } -func (s IntegrationTestSuite) TestNewJoinPoolCmd() { - val := s.network.Validators[0] - - info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewJoinPoolAddr", keyring.English, sdk.FullFundraiserPath, "", hd.Secp256k1) - s.Require().NoError(err) - - newAddr := sdk.AccAddress(info.GetPubKey().Address()) - - _, err = banktestutil.MsgSendExec( - val.ClientCtx, - val.Address, - newAddr, - sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 20000), sdk.NewInt64Coin("node0token", 20000)), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - osmoutils.DefaultFeeString(s.cfg), - ) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - expectedCode uint32 - }{ - { - "join pool with insufficient balance", - []string{ - fmt.Sprintf("--%s=%d", cli.FlagPoolId, 1), - fmt.Sprintf("--%s=%s", cli.FlagMaxAmountsIn, "100stake,100node0token"), - fmt.Sprintf("--%s=%s", cli.FlagShareAmountOut, "1000000000000000000000"), - fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), - }, - false, &sdk.TxResponse{}, 6, - }, - { - "join pool with sufficient balance", - []string{ // join-pool --pool-id=1 --max-amounts-in=100stake --share-amount-out=100 --from=validator --keyring-backend=test --chain-id=testing --yes - fmt.Sprintf("--%s=%d", cli.FlagPoolId, 1), - fmt.Sprintf("--%s=%s", cli.FlagMaxAmountsIn, "100stake,100node0token"), - fmt.Sprintf("--%s=%s", cli.FlagShareAmountOut, "10000000000000000000"), - fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), +func TestNewJoinPoolCmd(t *testing.T) { + desc, _ := cli.NewJoinPoolCmd() + tcs := map[string]osmocli.TxCliTestCase[*types.MsgJoinPool]{ + "join pool": { + Cmd: "--pool-id=1 --pool-id=1 --max-amounts-in=100stake --share-amount-out=100 --from=" + testAddresses[0].String(), + ExpectedMsg: &types.MsgJoinPool{ + Sender: testAddresses[0].String(), + PoolId: 1, + ShareOutAmount: sdk.NewIntFromUint64(100), + TokenInMaxs: sdk.NewCoins(sdk.NewInt64Coin("stake", 100)), }, - false, &sdk.TxResponse{}, 0, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewJoinPoolCmd() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } -} - -func (s IntegrationTestSuite) TestNewExitPoolCmd() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - expectedCode uint32 - }{ - { - "ask too much when exit", - []string{ // --min-amounts-out=100stake --pool-id=1 --share-amount-in=10 --from=validator --keyring-backend=test --chain-id=testing --yes - fmt.Sprintf("--%s=%d", cli.FlagPoolId, 1), - fmt.Sprintf("--%s=%s", cli.FlagShareAmountIn, "20000000000000000000"), - fmt.Sprintf("--%s=%s", cli.FlagMinAmountsOut, "20stake"), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), - }, - false, &sdk.TxResponse{}, 7, - }, - { - "ask enough when exit", - []string{ // --min-amounts-out=100stake --pool-id=1 --share-amount-in=10 --from=validator --keyring-backend=test --chain-id=testing --yes - fmt.Sprintf("--%s=%d", cli.FlagPoolId, 1), - fmt.Sprintf("--%s=%s", cli.FlagShareAmountIn, "20000000000000000000"), - fmt.Sprintf("--%s=%s", cli.FlagMinAmountsOut, "10stake"), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), - }, - false, &sdk.TxResponse{}, 0, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewExitPoolCmd() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } + osmocli.RunTxTestCases(t, desc, tcs) } -func (s IntegrationTestSuite) TestNewSwapExactAmountOutCmd() { - val := s.network.Validators[0] - - info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewSwapExactAmountOut", - keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) - s.Require().NoError(err) - - newAddr := sdk.AccAddress(info.GetPubKey().Address()) - - _, err = banktestutil.MsgSendExec( - val.ClientCtx, - val.Address, - newAddr, - sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 20000), sdk.NewInt64Coin("node0token", 20000)), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - osmoutils.DefaultFeeString(s.cfg), - ) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - - expectErr bool - respType proto.Message - expectedCode uint32 - }{ - { - "swap exact amount out", // osmosisd tx gamm swap-exact-amount-out 10stake 20 --swap-route-pool-ids=1 --swap-route-denoms=node0token --from=validator --keyring-backend=test --chain-id=testing --yes - []string{ - "10stake", "20", - fmt.Sprintf("--%s=%d", cli.FlagSwapRoutePoolIds, 1), - fmt.Sprintf("--%s=%s", cli.FlagSwapRouteDenoms, "node0token"), - fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), +func TestNewExitPoolCmd(t *testing.T) { + desc, _ := cli.NewExitPoolCmd() + tcs := map[string]osmocli.TxCliTestCase[*types.MsgExitPool]{ + "exit pool": { + Cmd: "--min-amounts-out=100stake --pool-id=1 --share-amount-in=10 --from=" + testAddresses[0].String(), + ExpectedMsg: &types.MsgExitPool{ + Sender: testAddresses[0].String(), + PoolId: 1, + ShareInAmount: sdk.NewIntFromUint64(10), + TokenOutMins: sdk.NewCoins(sdk.NewInt64Coin("stake", 100)), }, - false, &sdk.TxResponse{}, 0, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewSwapExactAmountOutCmd() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } + osmocli.RunTxTestCases(t, desc, tcs) } -func (s IntegrationTestSuite) TestNewJoinSwapExternAmountInCmd() { - val := s.network.Validators[0] - - info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewJoinSwapExternAmountIn", - keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) - s.Require().NoError(err) - - newAddr := sdk.AccAddress(info.GetPubKey().Address()) - - _, err = banktestutil.MsgSendExec( - val.ClientCtx, - val.Address, - newAddr, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(20000))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - osmoutils.DefaultFeeString(s.cfg), - ) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - expectedCode uint32 - }{ - { - "join swap extern amount in", // osmosisd tx gamm join-swap-extern-amount-in --pool-id=1 10stake 1 --from=validator --keyring-backend=test --chain-id=testing --yes - []string{ - "10stake", "1", - fmt.Sprintf("--%s=%d", cli.FlagPoolId, 1), - fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), +func TestNewSwapExactAmountOutCmd(t *testing.T) { + desc, _ := cli.NewSwapExactAmountOutCmd() + tcs := map[string]osmocli.TxCliTestCase[*types.MsgSwapExactAmountOut]{ + "swap exact amount out": { + Cmd: "10stake 20 --swap-route-pool-ids=1 --swap-route-denoms=node0token --from=" + testAddresses[0].String(), + ExpectedMsg: &types.MsgSwapExactAmountOut{ + Sender: testAddresses[0].String(), + Routes: []types.SwapAmountOutRoute{{PoolId: 1, TokenInDenom: "node0token"}}, + TokenInMaxAmount: sdk.NewIntFromUint64(20), + TokenOut: sdk.NewInt64Coin("stake", 10), }, - false, &sdk.TxResponse{}, 0, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewJoinSwapExternAmountIn() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } + osmocli.RunTxTestCases(t, desc, tcs) } -func (s IntegrationTestSuite) TestNewExitSwapExternAmountOutCmd() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - expectedCode uint32 - }{ - { - "exit swap extern amount out", // osmosisd tx gamm exit-swap-extern-amount-out --pool-id=1 10stake 1 --from=validator --keyring-backend=test --chain-id=testing --yes - []string{ - "10stake", "10000000000000000000", - fmt.Sprintf("--%s=%d", cli.FlagPoolId, 1), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), +func TestNewSwapExactAmountInCmd(t *testing.T) { + desc, _ := cli.NewSwapExactAmountInCmd() + tcs := map[string]osmocli.TxCliTestCase[*types.MsgSwapExactAmountIn]{ + "swap exact amount in": { + Cmd: "10stake 3 --swap-route-pool-ids=1 --swap-route-denoms=node0token --from=" + testAddresses[0].String(), + ExpectedMsg: &types.MsgSwapExactAmountIn{ + Sender: testAddresses[0].String(), + Routes: []types.SwapAmountInRoute{{PoolId: 1, TokenOutDenom: "node0token"}}, + TokenIn: sdk.NewInt64Coin("stake", 10), + TokenOutMinAmount: sdk.NewIntFromUint64(3), }, - false, &sdk.TxResponse{}, 0, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewExitSwapExternAmountOut() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } + osmocli.RunTxTestCases(t, desc, tcs) } -func (s IntegrationTestSuite) TestNewJoinSwapShareAmountOutCmd() { - val := s.network.Validators[0] - - info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewJoinSwapShareAmountOutAddr", keyring.English, - sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) - s.Require().NoError(err) - - newAddr := sdk.AccAddress(info.GetPubKey().Address()) - - _, err = banktestutil.MsgSendExec( - val.ClientCtx, - val.Address, - newAddr, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(20000))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - osmoutils.DefaultFeeString(s.cfg), - ) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - expectedCode uint32 - }{ - { - "join swap share amount out", // osmosisd tx gamm join-swap-share-amount-out --pool-id=1 stake 10 1 --from=validator --keyring-backend=test --chain-id=testing --yes - []string{ - "stake", "50", "5000000000000000000", - fmt.Sprintf("--%s=%d", cli.FlagPoolId, 1), - fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), +func TestNewJoinSwapExternAmountInCmd(t *testing.T) { + desc, _ := cli.NewJoinSwapExternAmountIn() + tcs := map[string]osmocli.TxCliTestCase[*types.MsgJoinSwapExternAmountIn]{ + "swap exact amount in": { + Cmd: "10stake 1 --pool-id=1 --from=" + testAddresses[0].String(), + ExpectedMsg: &types.MsgJoinSwapExternAmountIn{ + Sender: testAddresses[0].String(), + PoolId: 1, + TokenIn: sdk.NewInt64Coin("stake", 10), + ShareOutMinAmount: sdk.NewIntFromUint64(1), }, - false, &sdk.TxResponse{}, 0, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewJoinSwapShareAmountOut() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } + osmocli.RunTxTestCases(t, desc, tcs) } -func (s IntegrationTestSuite) TestNewExitSwapShareAmountInCmd() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - expectedCode uint32 - }{ - { - "exit swap share amount in", // osmosisd tx gamm exit-swap-share-amount-in --pool-id=1 stake 10 1 --from=validator --keyring-backend=test --chain-id=testing --yes - []string{ - "stake", "10000000000000000000", "1", - fmt.Sprintf("--%s=%d", cli.FlagPoolId, 1), - fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), +func TestNewJoinSwapShareAmountOutCmd(t *testing.T) { + desc, _ := cli.NewJoinSwapShareAmountOut() + tcs := map[string]osmocli.TxCliTestCase[*types.MsgJoinSwapShareAmountOut]{ + "swap exact amount in": { + Cmd: "stake 10 1 --pool-id=1 --from=" + testAddresses[0].String(), + ExpectedMsg: &types.MsgJoinSwapShareAmountOut{ + Sender: testAddresses[0].String(), + PoolId: 1, + TokenInDenom: "stake", + ShareOutAmount: sdk.NewIntFromUint64(10), + TokenInMaxAmount: sdk.NewIntFromUint64(1), }, - false, &sdk.TxResponse{}, 0, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewExitSwapShareAmountIn() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } + osmocli.RunTxTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestGetCmdPools() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - }{ - { - "query pools", - []string{ - fmt.Sprintf("--%s=%s", tmcli.OutputFlag, "json"), +func TestNewExitSwapExternAmountOutCmd(t *testing.T) { + desc, _ := cli.NewExitSwapExternAmountOut() + tcs := map[string]osmocli.TxCliTestCase[*types.MsgExitSwapExternAmountOut]{ + "swap exact amount in": { + Cmd: "10stake 1 --pool-id=1 --from=" + testAddresses[0].String(), + ExpectedMsg: &types.MsgExitSwapExternAmountOut{ + Sender: testAddresses[0].String(), + PoolId: 1, + TokenOut: sdk.NewInt64Coin("stake", 10), + ShareInMaxAmount: sdk.NewIntFromUint64(1), }, - false, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdPools() // osmosisd query gamm pools - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - resp := types.QueryPoolsResponse{} - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - - s.Require().Greater(len(resp.Pools), 0, out.String()) - } - }) - } + osmocli.RunTxTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestGetCmdNumPools() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - }{ - { - "query num-pools", - []string{ - fmt.Sprintf("--%s=%s", tmcli.OutputFlag, "json"), +func TestNewExitSwapShareAmountInCmd(t *testing.T) { + desc, _ := cli.NewExitSwapShareAmountIn() + tcs := map[string]osmocli.TxCliTestCase[*types.MsgExitSwapShareAmountIn]{ + "swap exact amount in": { + Cmd: "stake 10 1 --pool-id=1 --from=" + testAddresses[0].String(), + ExpectedMsg: &types.MsgExitSwapShareAmountIn{ + Sender: testAddresses[0].String(), + PoolId: 1, + TokenOutDenom: "stake", + ShareInAmount: sdk.NewIntFromUint64(10), + TokenOutMinAmount: sdk.NewIntFromUint64(1), }, - false, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdNumPools() // osmosisd query gamm num-pools - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - resp := types.QueryNumPoolsResponse{} - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - - s.Require().Greater(resp.NumPools, uint64(0), out.String()) - } - }) - } + osmocli.RunTxTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestGetCmdPool() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - }{ - { - "query pool by id", // osmosisd query gamm pool 1 - []string{ - "1", - fmt.Sprintf("--%s=%s", tmcli.OutputFlag, "json"), +func TestGetCmdPools(t *testing.T) { + desc, _ := cli.GetCmdPools() + tcs := map[string]osmocli.QueryCliTestCase[*types.QueryPoolsRequest]{ + "basic test": { + Cmd: "--offset=2", + ExpectedQuery: &types.QueryPoolsRequest{ + Pagination: &query.PageRequest{Key: []uint8{}, Offset: 2, Limit: 100}, }, - false, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdPool() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - - resp := types.QueryPoolResponse{} - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - } - }) - } + osmocli.RunQueryTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestGetCmdTotalShares() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - }{ - { - "query pool total share by id", // osmosisd query gamm total-share 1 - []string{ - "1", - fmt.Sprintf("--%s=%s", tmcli.OutputFlag, "json"), - }, - false, +func TestGetCmdPool(t *testing.T) { + desc, _ := cli.GetCmdPool() + tcs := map[string]osmocli.QueryCliTestCase[*types.QueryPoolRequest]{ + "basic test": { + Cmd: "1", + ExpectedQuery: &types.QueryPoolRequest{PoolId: 1}, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdTotalShares() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - resp := types.QueryTotalSharesResponse{} - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - } - }) - } + osmocli.RunQueryTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestGetCmdTotalLiquidity() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - }{ - { - "query total liquidity", // osmosisd query gamm total-liquidity - []string{ - fmt.Sprintf("--%s=%s", tmcli.OutputFlag, "json"), +func TestGetCmdSpotPrice(t *testing.T) { + desc, _ := cli.GetCmdSpotPrice() + tcs := map[string]osmocli.QueryCliTestCase[*types.QuerySpotPriceRequest]{ + "basic test": { + Cmd: "1 uosmo ibc/111", + ExpectedQuery: &types.QuerySpotPriceRequest{ + PoolId: 1, + BaseAssetDenom: "uosmo", + QuoteAssetDenom: "ibc/111", }, - false, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryTotalLiquidity() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - resp := types.QueryTotalLiquidityResponse{} - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - } - }) - } + osmocli.RunQueryTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestGetCmdSpotPrice() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - }{ - { - "query pool spot price", // osmosisd query gamm spot-price 1 stake node0token - []string{ - "1", "stake", "node0token", - fmt.Sprintf("--%s=%s", tmcli.OutputFlag, "json"), +func TestGetCmdEstimateSwapExactAmountIn(t *testing.T) { + desc, _ := cli.GetCmdEstimateSwapExactAmountIn() + tcs := map[string]osmocli.QueryCliTestCase[*types.QuerySwapExactAmountInRequest]{ + "basic test": { + Cmd: "1 osm11vmx8jtggpd9u7qr0t8vxclycz85u925sazglr7 10stake --swap-route-pool-ids=2 --swap-route-denoms=node0token", + ExpectedQuery: &types.QuerySwapExactAmountInRequest{ + Sender: "osm11vmx8jtggpd9u7qr0t8vxclycz85u925sazglr7", + PoolId: 1, + TokenIn: "10stake", + Routes: []types.SwapAmountInRoute{{PoolId: 2, TokenOutDenom: "node0token"}}, }, - false, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdSpotPrice() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - resp := types.QuerySpotPriceResponse{} - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) - } - }) - } + osmocli.RunQueryTestCases(t, desc, tcs) } -// func (s *IntegrationTestSuite) TestGetCmdEstimateSwapExactAmountIn() { -// val := s.network.Validators[0] - -// testCases := []struct { -// name string -// args []string -// expectErr bool -// }{ -// { -// "query pool estimate swap exact amount in", // osmosisd query gamm estimate-swap-exact-amount-in 1 cosmos1n8skk06h3kyh550ad9qketlfhc2l5dsdevd3hq 10.0stake --swap-route-pool-ids=1 --swap-route-denoms=node0token -// []string{ -// "1", -// "cosmos1n8skk06h3kyh550ad9qketlfhc2l5dsdevd3hq", -// "10.0stake", -// fmt.Sprintf("--%s=%d", cli.FlagSwapRoutePoolIds, 1), -// fmt.Sprintf("--%s=%s", cli.FlagSwapRouteDenoms, "node0token"), -// fmt.Sprintf("--%s=%s", tmcli.OutputFlag, "json"), -// }, -// false, -// }, -// } - -// for _, tc := range testCases { -// tc := tc - -// s.Run(tc.name, func() { -// cmd := cli.GetCmdEstimateSwapExactAmountIn() -// clientCtx := val.ClientCtx - -// out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) -// if tc.expectErr { -// s.Require().Error(err) -// } else { -// resp := types.QuerySwapExactAmountInResponse{} -// s.Require().NoError(err, out.String()) -// s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) -// } -// }) -// } -// } - -// func (s *IntegrationTestSuite) TestGetCmdEstimateSwapExactAmountOut() { -// val := s.network.Validators[0] - -// testCases := []struct { -// name string -// args []string -// expectErr bool -// }{ -// { -// "query pool estimate swap exact amount in", // osmosisd query gamm estimate-swap-exact-amount-in 1 cosmos1n8skk06h3kyh550ad9qketlfhc2l5dsdevd3hq 10.0stake --swap-route-pool-ids=1 --swap-route-denoms=node0token -// []string{ -// "1", -// val.Address.String(), -// "10.0stake", -// fmt.Sprintf("--%s=%d", cli.FlagSwapRoutePoolIds, 1), -// fmt.Sprintf("--%s=%s", cli.FlagSwapRouteDenoms, "node0token"), -// fmt.Sprintf("--%s=%s", tmcli.OutputFlag, "json"), -// }, -// false, -// }, -// } - -// for _, tc := range testCases { -// tc := tc - -// s.Run(tc.name, func() { -// cmd := cli.GetCmdEstimateSwapExactAmountOut() -// clientCtx := val.ClientCtx - -// out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) -// if tc.expectErr { -// s.Require().Error(err) -// } else { -// resp := types.QuerySwapExactAmountOutResponse{} -// s.Require().NoError(err, out.String()) -// s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) -// } -// }) -// } -// } - -func (s IntegrationTestSuite) TestNewSwapExactAmountInCmd() { - val := s.network.Validators[0] - - info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewSwapExactAmountIn", - keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) - s.Require().NoError(err) - - newAddr := sdk.AccAddress(info.GetPubKey().Address()) - - _, err = banktestutil.MsgSendExec( - val.ClientCtx, - val.Address, - newAddr, - sdk.NewCoins(sdk.NewInt64Coin(s.cfg.BondDenom, 20000), sdk.NewInt64Coin("node0token", 20000)), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - osmoutils.DefaultFeeString(s.cfg), - ) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - - expectErr bool - respType proto.Message - expectedCode uint32 - }{ - { - "swap exact amount in", // osmosisd tx gamm swap-exact-amount-in 10stake 3 --swap-route-pool-ids=1 --swap-route-denoms=node0token --from=validator --keyring-backend=test --chain-id=testing --yes - []string{ - "10stake", "3", - fmt.Sprintf("--%s=%d", cli.FlagSwapRoutePoolIds, 1), - fmt.Sprintf("--%s=%s", cli.FlagSwapRouteDenoms, "node0token"), - fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), +func TestGetCmdEstimateSwapExactAmountOut(t *testing.T) { + desc, _ := cli.GetCmdEstimateSwapExactAmountOut() + tcs := map[string]osmocli.QueryCliTestCase[*types.QuerySwapExactAmountOutRequest]{ + "basic test": { + Cmd: "1 osm11vmx8jtggpd9u7qr0t8vxclycz85u925sazglr7 10stake --swap-route-pool-ids=2 --swap-route-denoms=node0token", + ExpectedQuery: &types.QuerySwapExactAmountOutRequest{ + Sender: "osm11vmx8jtggpd9u7qr0t8vxclycz85u925sazglr7", + PoolId: 1, + TokenOut: "10stake", + Routes: []types.SwapAmountOutRoute{{PoolId: 2, TokenInDenom: "node0token"}}, }, - false, &sdk.TxResponse{}, 0, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewSwapExactAmountInCmd() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } -} - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) + osmocli.RunQueryTestCases(t, desc, tcs) } diff --git a/x/gamm/client/cli/flags.go b/x/gamm/client/cli/flags.go index 05ef34caccc..20042d3e8f0 100644 --- a/x/gamm/client/cli/flags.go +++ b/x/gamm/client/cli/flags.go @@ -66,38 +66,30 @@ type smoothWeightChangeParamsInputs struct { TargetPoolWeights string `json:"target-pool-weights"` } -func FlagSetQuerySwapRoutes() *flag.FlagSet { +func FlagSetMultihopSwapRoutes() *flag.FlagSet { fs := flag.NewFlagSet("", flag.ContinueOnError) - fs.String(FlagSwapRoutePoolIds, "", "swap route pool id") fs.String(FlagSwapRouteDenoms, "", "swap route amount") return fs } -func FlagSetSwapAmountOutRoutes() *flag.FlagSet { +func FlagSetCreatePoolFile() *flag.FlagSet { fs := flag.NewFlagSet("", flag.ContinueOnError) - - fs.String(FlagSwapRoutePoolIds, "", "swap route pool ids") - fs.String(FlagSwapRouteDenoms, "", "swap route denoms") + fs.String(FlagPoolFile, "", "Pool json file path (if this path is given, other create pool flags should not be used)") return fs } -func FlagSetCreatePool() *flag.FlagSet { +func FlagSetCreatePoolType() *flag.FlagSet { fs := flag.NewFlagSet("", flag.ContinueOnError) - - fs.String(FlagPoolFile, "", "Pool json file path (if this path is given, other create pool flags should not be used)") fs.String(FlagPoolType, "uniswap", "Pool type (either \"balancer\", \"uniswap\", or \"stableswap\"") - return fs } func FlagSetJoinPool() *flag.FlagSet { fs := flag.NewFlagSet("", flag.ContinueOnError) - fs.Uint64(FlagPoolId, 0, "The id of pool") fs.String(FlagShareAmountOut, "", "Minimum amount of Gamm tokens to receive") fs.StringArray(FlagMaxAmountsIn, []string{""}, "Maximum amount of each denom to send into the pool (specify multiple denoms with: --max-amounts-in=1uosmo --max-amounts-in=1uion)") - return fs } diff --git a/x/gamm/client/cli/query.go b/x/gamm/client/cli/query.go index b91c01ffe3a..4db20574251 100644 --- a/x/gamm/client/cli/query.go +++ b/x/gamm/client/cli/query.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" + "github.com/gogo/protobuf/proto" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -14,6 +15,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" "github.com/spf13/cobra" + flag "github.com/spf13/pflag" "gopkg.in/yaml.v2" "github.com/osmosis-labs/osmosis/v13/osmoutils/osmocli" @@ -24,17 +26,16 @@ import ( // GetQueryCmd returns the cli query commands for this module. func GetQueryCmd() *cobra.Command { cmd := osmocli.QueryIndexCmd(types.ModuleName) - + osmocli.AddQueryCmd(cmd, types.NewQueryClient, GetCmdSpotPrice) + osmocli.AddQueryCmd(cmd, types.NewQueryClient, GetCmdPool) + osmocli.AddQueryCmd(cmd, types.NewQueryClient, GetCmdPools) + osmocli.AddQueryCmd(cmd, types.NewQueryClient, GetCmdEstimateSwapExactAmountIn) + osmocli.AddQueryCmd(cmd, types.NewQueryClient, GetCmdEstimateSwapExactAmountOut) cmd.AddCommand( - GetCmdPool(), - GetCmdPools(), GetCmdNumPools(), GetCmdPoolParams(), GetCmdTotalShares(), - GetCmdSpotPrice(), GetCmdQueryTotalLiquidity(), - GetCmdEstimateSwapExactAmountIn(), - GetCmdEstimateSwapExactAmountOut(), GetCmdTotalPoolLiquidity(), GetCmdQueryPoolsWithFilter(), GetCmdPoolType(), @@ -43,16 +44,12 @@ func GetQueryCmd() *cobra.Command { return cmd } -func GetCmdPool() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.QueryPoolRequest]( - "pool [poolID]", - "Query pool", - `Query pool. -Example: -{{.CommandPrefix}} pool 1 -`, - types.ModuleName, types.NewQueryClient, - ) +func GetCmdPool() (*osmocli.QueryDescriptor, *types.QueryPoolRequest) { + return &osmocli.QueryDescriptor{ + Use: "pool [poolID]", + Short: "Query pool", + Long: `{{.Short}}{{.ExampleHeader}} +{{.CommandPrefix}} pool 1`}, &types.QueryPoolRequest{} } // TODO: Push this to the SDK. @@ -77,14 +74,12 @@ func writeOutputBoilerplate(ctx client.Context, out []byte) error { return nil } -func GetCmdPools() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.QueryPoolsRequest]( - "pools", - "Query pools", - `{{.Short}}{{.ExampleHeader}} -{{.CommandPrefix}} pools`, - types.ModuleName, types.NewQueryClient, - ) +func GetCmdPools() (*osmocli.QueryDescriptor, *types.QueryPoolsRequest) { + return &osmocli.QueryDescriptor{ + Use: "pools", + Short: "Query pools", + Long: `{{.Short}}{{.ExampleHeader}} +{{.CommandPrefix}} pools`}, &types.QueryPoolsRequest{} } func GetCmdNumPools() *cobra.Command { @@ -192,123 +187,76 @@ Example: ) } -func GetCmdSpotPrice() *cobra.Command { - //nolint:staticcheck - return osmocli.SimpleQueryCmd[*types.QuerySpotPriceRequest]( - "spot-price [quote-asset-denom] [base-asset-denom]", - "Query spot-price (LEGACY, arguments are reversed!!)", - `Query spot price (Legacy). -Example: +//nolint:staticcheck +func GetCmdSpotPrice() (*osmocli.QueryDescriptor, *types.QuerySpotPriceRequest) { + return &osmocli.QueryDescriptor{ + Use: "spot-price [quote-asset-denom] [base-asset-denom]", + Short: "Query spot-price (LEGACY, arguments are reversed!!)", + Long: `Query spot price (Legacy).{{.ExampleHeader}} {{.CommandPrefix}} spot-price 1 uosmo ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2 -`, - types.ModuleName, types.NewQueryClient, - ) +`}, &types.QuerySpotPriceRequest{} } // GetCmdEstimateSwapExactAmountIn returns estimation of output coin when amount of x token input. -func GetCmdEstimateSwapExactAmountIn() *cobra.Command { - cmd := &cobra.Command{ +func GetCmdEstimateSwapExactAmountIn() (*osmocli.QueryDescriptor, *types.QuerySwapExactAmountInRequest) { + return &osmocli.QueryDescriptor{ Use: "estimate-swap-exact-amount-in ", Short: "Query estimate-swap-exact-amount-in", - Long: strings.TrimSpace( - fmt.Sprintf(`Query estimate-swap-exact-amount-in. -Example: -$ %s query gamm estimate-swap-exact-amount-in 1 osm11vmx8jtggpd9u7qr0t8vxclycz85u925sazglr7 stake --swap-route-pool-ids=2 --swap-route-pool-ids=3 -`, - version.AppName, - ), - ), - Args: cobra.ExactArgs(3), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - poolID, err := strconv.Atoi(args[0]) - if err != nil { - return err - } - - routes, err := swapAmountInRoutes(cmd.Flags()) - if err != nil { - return err - } - - res, err := queryClient.EstimateSwapExactAmountIn(cmd.Context(), &types.QuerySwapExactAmountInRequest{ - Sender: args[1], // TODO: where sender is used? - PoolId: uint64(poolID), // TODO: is this poolId used? - TokenIn: args[2], - Routes: routes, - }) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - cmd.Flags().AddFlagSet(FlagSetQuerySwapRoutes()) - flags.AddQueryFlagsToCmd(cmd) - _ = cmd.MarkFlagRequired(FlagSwapRoutePoolIds) - _ = cmd.MarkFlagRequired(FlagSwapRouteDenoms) - - return cmd + Long: `Query estimate-swap-exact-amount-in.{{.ExampleHeader}} +{{.CommandPrefix}} estimate-swap-exact-amount-in 1 osm11vmx8jtggpd9u7qr0t8vxclycz85u925sazglr7 stake --swap-route-pool-ids=2 --swap-route-pool-ids=3`, + ParseQuery: EstimateSwapExactAmountInParseArgs, + Flags: osmocli.FlagDesc{RequiredFlags: []*flag.FlagSet{FlagSetMultihopSwapRoutes()}}, + }, &types.QuerySwapExactAmountInRequest{} } // GetCmdEstimateSwapExactAmountOut returns estimation of input coin to get exact amount of x token output. -func GetCmdEstimateSwapExactAmountOut() *cobra.Command { - cmd := &cobra.Command{ +func GetCmdEstimateSwapExactAmountOut() (*osmocli.QueryDescriptor, *types.QuerySwapExactAmountOutRequest) { + return &osmocli.QueryDescriptor{ Use: "estimate-swap-exact-amount-out ", Short: "Query estimate-swap-exact-amount-out", - Long: strings.TrimSpace( - fmt.Sprintf(`Query estimate-swap-exact-amount-out. -Example: -$ %s query gamm estimate-swap-exact-amount-out 1 osm11vmx8jtggpd9u7qr0t8vxclycz85u925sazglr7 stake --swap-route-pool-ids=2 --swap-route-pool-ids=3 -`, - version.AppName, - ), - ), - Args: cobra.ExactArgs(3), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) + Long: `Query estimate-swap-exact-amount-out.{{.ExampleHeader}} +{{.CommandPrefix}} estimate-swap-exact-amount-out 1 osm11vmx8jtggpd9u7qr0t8vxclycz85u925sazglr7 stake --swap-route-pool-ids=2 --swap-route-pool-ids=3`, + ParseQuery: EstimateSwapExactAmountOutParseArgs, + Flags: osmocli.FlagDesc{RequiredFlags: []*flag.FlagSet{FlagSetMultihopSwapRoutes()}}, + }, &types.QuerySwapExactAmountOutRequest{} +} - poolID, err := strconv.Atoi(args[0]) - if err != nil { - return err - } +func EstimateSwapExactAmountInParseArgs(args []string, fs *flag.FlagSet) (proto.Message, error) { + poolID, err := strconv.Atoi(args[0]) + if err != nil { + return nil, err + } - routes, err := swapAmountOutRoutes(cmd.Flags()) - if err != nil { - return err - } + routes, err := swapAmountInRoutes(fs) + if err != nil { + return nil, err + } - res, err := queryClient.EstimateSwapExactAmountOut(cmd.Context(), &types.QuerySwapExactAmountOutRequest{ - Sender: args[1], // TODO: where sender is used? - PoolId: uint64(poolID), // TODO: is this poolId used? - Routes: routes, - TokenOut: args[2], - }) - if err != nil { - return err - } + return &types.QuerySwapExactAmountInRequest{ + Sender: args[1], // TODO: where sender is used? + PoolId: uint64(poolID), // TODO: is this poolId used? + TokenIn: args[2], + Routes: routes, + }, nil +} - return clientCtx.PrintProto(res) - }, +func EstimateSwapExactAmountOutParseArgs(args []string, fs *flag.FlagSet) (proto.Message, error) { + poolID, err := strconv.Atoi(args[0]) + if err != nil { + return nil, err } - cmd.Flags().AddFlagSet(FlagSetQuerySwapRoutes()) - flags.AddQueryFlagsToCmd(cmd) - _ = cmd.MarkFlagRequired(FlagSwapRoutePoolIds) - _ = cmd.MarkFlagRequired(FlagSwapRouteDenoms) + routes, err := swapAmountOutRoutes(fs) + if err != nil { + return nil, err + } - return cmd + return &types.QuerySwapExactAmountOutRequest{ + Sender: args[1], // TODO: where sender is used? + PoolId: uint64(poolID), // TODO: is this poolId used? + Routes: routes, + TokenOut: args[2], + }, nil } // GetCmdQueryPoolsWithFilter returns pool with filter diff --git a/x/gamm/client/cli/tx.go b/x/gamm/client/cli/tx.go index 23c3fbd3181..cdff3221315 100644 --- a/x/gamm/client/cli/tx.go +++ b/x/gamm/client/cli/tx.go @@ -16,33 +16,23 @@ import ( "github.com/osmosis-labs/osmosis/v13/x/gamm/types" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/tx" sdk "github.com/cosmos/cosmos-sdk/types" ) func NewTxCmd() *cobra.Command { - txCmd := &cobra.Command{ - Use: types.ModuleName, - Short: "Generalized automated market maker transaction subcommands", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - + txCmd := osmocli.TxIndexCmd(types.ModuleName) + osmocli.AddTxCmd(txCmd, NewJoinPoolCmd) + osmocli.AddTxCmd(txCmd, NewExitPoolCmd) + osmocli.AddTxCmd(txCmd, NewSwapExactAmountInCmd) + osmocli.AddTxCmd(txCmd, NewSwapExactAmountOutCmd) + osmocli.AddTxCmd(txCmd, NewJoinSwapExternAmountIn) + osmocli.AddTxCmd(txCmd, NewJoinSwapShareAmountOut) + osmocli.AddTxCmd(txCmd, NewExitSwapExternAmountOut) + osmocli.AddTxCmd(txCmd, NewExitSwapShareAmountIn) txCmd.AddCommand( - NewCreatePoolCmd(), - NewJoinPoolCmd(), - NewExitPoolCmd(), - NewSwapExactAmountInCmd(), - NewSwapExactAmountOutCmd(), - NewJoinSwapExternAmountIn(), - NewJoinSwapShareAmountOut(), - NewExitSwapExternAmountOut(), - NewExitSwapShareAmountIn(), + NewCreatePoolCmd().BuildCommandCustomFn(), NewStableSwapAdjustScalingFactorsCmd(), ) - return txCmd } @@ -50,12 +40,12 @@ var poolIdFlagOverride = map[string]string{ "poolid": FlagPoolId, } -func NewCreatePoolCmd() *cobra.Command { - cmd := &cobra.Command{ +func NewCreatePoolCmd() *osmocli.TxCliDesc { + desc := osmocli.TxCliDesc{ Use: "create-pool [flags]", Short: "create a new pool and provide the liquidity to it", - Long: `Must provide path to a pool JSON file (--pool-file) describing the pool to be created`, - Example: `Sample pool JSON file contents for balancer: + Long: `Must provide path to a pool JSON file (--pool-file) describing the pool to be created +Sample pool JSON file contents for balancer: { "weights": "4uatom,4osmo,2uakt", "initial-deposit": "100uatom,5osmo,20uakt", @@ -73,49 +63,18 @@ For stableswap (demonstrating need for a 1:1000 scaling factor, see doc) "scaling-factors": "1000,1" } `, - Args: cobra.ExactArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - - txf := tx.NewFactoryCLI(clientCtx, cmd.Flags()). - WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever) - - poolType, err := cmd.Flags().GetString(FlagPoolType) - if err != nil { - return err - } - poolType = strings.ToLower(poolType) - - var msg sdk.Msg - if poolType == "balancer" || poolType == "uniswap" { - msg, err = NewBuildCreateBalancerPoolMsg(clientCtx, cmd.Flags()) - if err != nil { - return err - } - } else if poolType == "stableswap" { - msg, err = NewBuildCreateStableswapPoolMsg(clientCtx, cmd.Flags()) - if err != nil { - return err - } - } - - return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg) + NumArgs: 0, + ParseAndBuildMsg: BuildCreatePoolCmd, + Flags: osmocli.FlagDesc{ + RequiredFlags: []*flag.FlagSet{FlagSetCreatePoolFile()}, + OptionalFlags: []*flag.FlagSet{FlagSetCreatePoolType()}, }, } - - cmd.Flags().AddFlagSet(FlagSetCreatePool()) - flags.AddTxFlagsToCmd(cmd) - - _ = cmd.MarkFlagRequired(FlagPoolFile) - - return cmd + return &desc } -func NewJoinPoolCmd() *cobra.Command { - cmd := osmocli.BuildTxCli[*types.MsgJoinPool](&osmocli.TxCliDesc{ +func NewJoinPoolCmd() (*osmocli.TxCliDesc, *types.MsgJoinPool) { + return &osmocli.TxCliDesc{ Use: "join-pool", Short: "join a new pool and provide the liquidity to it", CustomFlagOverrides: map[string]string{ @@ -124,17 +83,13 @@ func NewJoinPoolCmd() *cobra.Command { }, CustomFieldParsers: map[string]osmocli.CustomFieldParserFn{ "TokenInMaxs": osmocli.FlagOnlyParser(maxAmountsInParser), - }}) - - cmd.Flags().AddFlagSet(FlagSetJoinPool()) - _ = cmd.MarkFlagRequired(FlagPoolId) - _ = cmd.MarkFlagRequired(FlagShareAmountOut) - _ = cmd.MarkFlagRequired(FlagMaxAmountsIn) - return cmd + }, + Flags: osmocli.FlagDesc{RequiredFlags: []*flag.FlagSet{FlagSetJoinPool()}}, + }, &types.MsgJoinPool{} } -func NewExitPoolCmd() *cobra.Command { - cmd := osmocli.BuildTxCli[*types.MsgExitPool](&osmocli.TxCliDesc{ +func NewExitPoolCmd() (*osmocli.TxCliDesc, *types.MsgExitPool) { + return &osmocli.TxCliDesc{ Use: "exit-pool", Short: "exit a new pool and withdraw the liquidity from it", CustomFlagOverrides: map[string]string{ @@ -143,90 +98,67 @@ func NewExitPoolCmd() *cobra.Command { }, CustomFieldParsers: map[string]osmocli.CustomFieldParserFn{ "TokenOutMins": osmocli.FlagOnlyParser(minAmountsOutParser), - }}) - - cmd.Flags().AddFlagSet(FlagSetExitPool()) - _ = cmd.MarkFlagRequired(FlagPoolId) - _ = cmd.MarkFlagRequired(FlagShareAmountIn) - _ = cmd.MarkFlagRequired(FlagMinAmountsOut) - return cmd + }, + Flags: osmocli.FlagDesc{RequiredFlags: []*flag.FlagSet{FlagSetExitPool()}}, + }, &types.MsgExitPool{} } -func NewSwapExactAmountInCmd() *cobra.Command { - cmd := osmocli.BuildTxCli[*types.MsgSwapExactAmountIn](&osmocli.TxCliDesc{ +func NewSwapExactAmountInCmd() (*osmocli.TxCliDesc, *types.MsgSwapExactAmountIn) { + return &osmocli.TxCliDesc{ Use: "swap-exact-amount-in [token-in] [token-out-min-amount]", Short: "swap exact amount in", CustomFieldParsers: map[string]osmocli.CustomFieldParserFn{ "Routes": osmocli.FlagOnlyParser(swapAmountInRoutes), - }}) - - cmd.Flags().AddFlagSet(FlagSetQuerySwapRoutes()) - _ = cmd.MarkFlagRequired(FlagSwapRoutePoolIds) - _ = cmd.MarkFlagRequired(FlagSwapRouteDenoms) - return cmd + }, + Flags: osmocli.FlagDesc{RequiredFlags: []*flag.FlagSet{FlagSetMultihopSwapRoutes()}}, + }, &types.MsgSwapExactAmountIn{} } -func NewSwapExactAmountOutCmd() *cobra.Command { +func NewSwapExactAmountOutCmd() (*osmocli.TxCliDesc, *types.MsgSwapExactAmountOut) { // Can't get rid of this parser without a break, because the args are out of order. - cmd := osmocli.TxCliDesc{ + return &osmocli.TxCliDesc{ Use: "swap-exact-amount-out [token-out] [token-in-max-amount]", Short: "swap exact amount out", NumArgs: 2, ParseAndBuildMsg: NewBuildSwapExactAmountOutMsg, - }.BuildCommandCustomFn() - - cmd.Flags().AddFlagSet(FlagSetSwapAmountOutRoutes()) - _ = cmd.MarkFlagRequired(FlagSwapRoutePoolIds) - _ = cmd.MarkFlagRequired(FlagSwapRouteDenoms) - return cmd + Flags: osmocli.FlagDesc{RequiredFlags: []*flag.FlagSet{FlagSetMultihopSwapRoutes()}}, + }, &types.MsgSwapExactAmountOut{} } -func NewJoinSwapExternAmountIn() *cobra.Command { - cmd := osmocli.BuildTxCli[*types.MsgJoinSwapExternAmountIn](&osmocli.TxCliDesc{ +func NewJoinSwapExternAmountIn() (*osmocli.TxCliDesc, *types.MsgJoinSwapExternAmountIn) { + return &osmocli.TxCliDesc{ Use: "join-swap-extern-amount-in [token-in] [share-out-min-amount]", Short: "join swap extern amount in", CustomFlagOverrides: poolIdFlagOverride, - }) - - cmd.Flags().AddFlagSet(FlagSetJustPoolId()) - _ = cmd.MarkFlagRequired(FlagPoolId) - return cmd + Flags: osmocli.FlagDesc{RequiredFlags: []*flag.FlagSet{FlagSetJustPoolId()}}, + }, &types.MsgJoinSwapExternAmountIn{} } -func NewJoinSwapShareAmountOut() *cobra.Command { - cmd := osmocli.BuildTxCli[*types.MsgJoinSwapShareAmountOut](&osmocli.TxCliDesc{ +func NewJoinSwapShareAmountOut() (*osmocli.TxCliDesc, *types.MsgJoinSwapShareAmountOut) { + return &osmocli.TxCliDesc{ Use: "join-swap-share-amount-out [token-in-denom] [token-in-max-amount] [share-out-amount]", Short: "join swap share amount out", CustomFlagOverrides: poolIdFlagOverride, - }) - - cmd.Flags().AddFlagSet(FlagSetJustPoolId()) - _ = cmd.MarkFlagRequired(FlagPoolId) - return cmd + Flags: osmocli.FlagDesc{RequiredFlags: []*flag.FlagSet{FlagSetJustPoolId()}}, + }, &types.MsgJoinSwapShareAmountOut{} } -func NewExitSwapExternAmountOut() *cobra.Command { - cmd := osmocli.BuildTxCli[*types.MsgExitSwapExternAmountOut](&osmocli.TxCliDesc{ +func NewExitSwapExternAmountOut() (*osmocli.TxCliDesc, *types.MsgExitSwapExternAmountOut) { + return &osmocli.TxCliDesc{ Use: "exit-swap-extern-amount-out [token-out] [share-in-max-amount]", Short: "exit swap extern amount out", CustomFlagOverrides: poolIdFlagOverride, - }) - - cmd.Flags().AddFlagSet(FlagSetJustPoolId()) - _ = cmd.MarkFlagRequired(FlagPoolId) - return cmd + Flags: osmocli.FlagDesc{RequiredFlags: []*flag.FlagSet{FlagSetJustPoolId()}}, + }, &types.MsgExitSwapExternAmountOut{} } -func NewExitSwapShareAmountIn() *cobra.Command { - cmd := osmocli.BuildTxCli[*types.MsgExitSwapShareAmountIn](&osmocli.TxCliDesc{ +func NewExitSwapShareAmountIn() (*osmocli.TxCliDesc, *types.MsgExitSwapShareAmountIn) { + return &osmocli.TxCliDesc{ Use: "exit-swap-share-amount-in [token-out-denom] [share-in-amount] [token-out-min-amount]", Short: "exit swap share amount in", CustomFlagOverrides: poolIdFlagOverride, - }) - - cmd.Flags().AddFlagSet(FlagSetJustPoolId()) - _ = cmd.MarkFlagRequired(FlagPoolId) - return cmd + Flags: osmocli.FlagDesc{RequiredFlags: []*flag.FlagSet{FlagSetJustPoolId()}}, + }, &types.MsgExitSwapShareAmountIn{} } // TODO: Change these flags to args. Required flags don't make that much sense. @@ -245,6 +177,28 @@ func NewStableSwapAdjustScalingFactorsCmd() *cobra.Command { return cmd } +func BuildCreatePoolCmd(clientCtx client.Context, args []string, fs *flag.FlagSet) (sdk.Msg, error) { + poolType, err := fs.GetString(FlagPoolType) + if err != nil { + return nil, err + } + poolType = strings.ToLower(poolType) + + var msg sdk.Msg + if poolType == "balancer" || poolType == "uniswap" { + msg, err = NewBuildCreateBalancerPoolMsg(clientCtx, fs) + if err != nil { + return nil, err + } + } else if poolType == "stableswap" { + msg, err = NewBuildCreateStableswapPoolMsg(clientCtx, fs) + if err != nil { + return nil, err + } + } + return msg, nil +} + func NewBuildCreateBalancerPoolMsg(clientCtx client.Context, fs *flag.FlagSet) (sdk.Msg, error) { pool, err := parseCreateBalancerPoolFlags(fs) if err != nil { diff --git a/x/gamm/client/testutil/test_helpers.go b/x/gamm/client/testutil/test_helpers.go deleted file mode 100644 index 9e68396c2c4..00000000000 --- a/x/gamm/client/testutil/test_helpers.go +++ /dev/null @@ -1,98 +0,0 @@ -package testutil - -import ( - "fmt" - "testing" - - gammcli "github.com/osmosis-labs/osmosis/v13/x/gamm/client/cli" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/testutil" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// commonArgs is args for CLI test commands. -var commonArgs = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), -} - -// MsgCreatePool broadcast a pool creation message. -func MsgCreatePool( - t *testing.T, - clientCtx client.Context, - owner fmt.Stringer, - tokenWeights string, - initialDeposit string, - swapFee string, - exitFee string, - futureGovernor string, - extraArgs ...string, -) (testutil.BufferWriter, error) { - args := []string{} - - jsonFile := testutil.WriteToNewTempFile(t, - fmt.Sprintf(` - { - "%s": "%s", - "%s": "%s", - "%s": "%s", - "%s": "%s", - "%s": "%s" - } - `, gammcli.PoolFileWeights, - tokenWeights, - gammcli.PoolFileInitialDeposit, - initialDeposit, - gammcli.PoolFileSwapFee, - swapFee, - gammcli.PoolFileExitFee, - exitFee, - gammcli.PoolFileExitFee, - exitFee, - ), - ) - - args = append(args, - fmt.Sprintf("--%s=%s", gammcli.FlagPoolFile, jsonFile.Name()), - fmt.Sprintf("--%s=%s", flags.FlagFrom, owner.String()), - fmt.Sprintf("--%s=%d", flags.FlagGas, 300000), - ) - - args = append(args, commonArgs...) - return clitestutil.ExecTestCLICmd(clientCtx, gammcli.NewCreatePoolCmd(), args) -} - -// MsgJoinPool broadcast pool join message. -func MsgJoinPool(clientCtx client.Context, owner fmt.Stringer, poolID uint64, shareAmtOut string, maxAmountsIn []string, extraArgs ...string) (testutil.BufferWriter, error) { - args := []string{ - fmt.Sprintf("--%s=%d", gammcli.FlagPoolId, poolID), - fmt.Sprintf("--%s=%s", gammcli.FlagShareAmountOut, shareAmtOut), - fmt.Sprintf("--%s=%s", flags.FlagFrom, owner.String()), - } - - for _, maxAmt := range maxAmountsIn { - args = append(args, fmt.Sprintf("--%s=%s", gammcli.FlagMaxAmountsIn, maxAmt)) - } - args = append(args, commonArgs...) - return clitestutil.ExecTestCLICmd(clientCtx, gammcli.NewJoinPoolCmd(), args) -} - -// MsgExitPool broadcast a pool exit message. -func MsgExitPool(clientCtx client.Context, owner fmt.Stringer, poolID uint64, shareAmtIn string, minAmountsOut []string, extraArgs ...string) (testutil.BufferWriter, error) { - args := []string{ - fmt.Sprintf("--%s=%d", gammcli.FlagPoolId, poolID), - fmt.Sprintf("--%s=%s", gammcli.FlagShareAmountIn, shareAmtIn), - fmt.Sprintf("--%s=%s", flags.FlagFrom, owner.String()), - } - - for _, maxAmt := range minAmountsOut { - args = append(args, fmt.Sprintf("--%s=%s", gammcli.FlagMinAmountsOut, maxAmt)) - } - - args = append(args, commonArgs...) - return clitestutil.ExecTestCLICmd(clientCtx, gammcli.NewExitPoolCmd(), args) -} diff --git a/x/incentives/client/cli/cli_test.go b/x/incentives/client/cli/cli_test.go index a2d7e75e844..f79c26c5bf9 100644 --- a/x/incentives/client/cli/cli_test.go +++ b/x/incentives/client/cli/cli_test.go @@ -1,393 +1,96 @@ -package cli_test +package cli import ( - "fmt" "testing" - "github.com/gogo/protobuf/proto" - "github.com/stretchr/testify/suite" + "github.com/cosmos/cosmos-sdk/types/query" - tmcli "github.com/tendermint/tendermint/libs/cli" - - gammtypes "github.com/osmosis-labs/osmosis/v13/x/gamm/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/osmosis-labs/osmosis/v13/app" - gammtestutil "github.com/osmosis-labs/osmosis/v13/x/gamm/client/testutil" - "github.com/osmosis-labs/osmosis/v13/x/incentives/client/cli" + "github.com/osmosis-labs/osmosis/v13/osmoutils" + "github.com/osmosis-labs/osmosis/v13/osmoutils/osmocli" "github.com/osmosis-labs/osmosis/v13/x/incentives/types" - lockuptestutil "github.com/osmosis-labs/osmosis/v13/x/lockup/client/testutil" - - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/cosmos/cosmos-sdk/testutil/network" ) -type IntegrationTestSuite struct { - suite.Suite - - cfg network.Config - network *network.Network -} - -func (s *IntegrationTestSuite) SetupSuite() { - s.T().Log("setting up integration test suite") - - s.cfg = app.DefaultConfig() - - // modification to pay pool creation fee with test bond denom "stake" - // marshal result into genesis json - genesisState := app.ModuleBasics.DefaultGenesis(s.cfg.Codec) - gammGen := gammtypes.DefaultGenesis() - gammGen.Params.PoolCreationFee = sdk.Coins{sdk.NewInt64Coin(s.cfg.BondDenom, 1000000)} - gammGenJson := s.cfg.Codec.MustMarshalJSON(gammGen) - genesisState[gammtypes.ModuleName] = gammGenJson - s.cfg.GenesisState = genesisState - - // create a network with a validator - s.network = network.New(s.T(), s.cfg) - val := s.network.Validators[0] - - // create a pool to receive gamm tokens - _, err := gammtestutil.MsgCreatePool(s.T(), val.ClientCtx, val.Address, "5stake,5node0token", "100stake,100node0token", "0.01", "0.01", "") - s.Require().NoError(err) - - _, err = s.network.WaitForHeight(1) - s.Require().NoError(err) - - lockAmt, err := sdk.ParseCoinNormalized(fmt.Sprint("100000gamm/pool/1")) - s.Require().NoError(err) - - _, err = s.network.WaitForHeight(1) - s.Require().NoError(err) - - // lock gamm pool tokens to create lock ID 1 - lockuptestutil.MsgLockTokens(val.ClientCtx, val.Address, lockAmt, "24h") - - _, err = s.network.WaitForHeight(1) - s.Require().NoError(err) - - secondLockAmt, err := sdk.ParseCoinNormalized(fmt.Sprint("100000gamm/pool/1")) - s.Require().NoError(err) - - _, err = s.network.WaitForHeight(1) - s.Require().NoError(err) - - // lock gamm pool tokens to create lock ID 2 - lockuptestutil.MsgLockTokens(val.ClientCtx, val.Address, secondLockAmt, "168h") - - _, err = s.network.WaitForHeight(1) - s.Require().NoError(err) -} - -func (s *IntegrationTestSuite) TearDownSuite() { - s.T().Log("tearing down integration test suite") - s.network.Cleanup() -} - -func (s *IntegrationTestSuite) TestGetCmdGauges() { - val := s.network.Validators[0] - - testCases := []struct { - name string - expectErr bool - args []string - respType proto.Message - }{ - { - "query gauges", - false, - []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, - &types.GaugesResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdGauges() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) - } -} - -func (s *IntegrationTestSuite) TestGetCmdToDistributeCoins() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - }{ - { - "query to distribute coins", - []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, - false, - &types.ModuleToDistributeCoinsResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdToDistributeCoins() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) - } -} +var testAddresses = osmoutils.CreateRandomAccounts(3) -func (s *IntegrationTestSuite) TestGetCmdGaugeByID() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - }{ - { - "query gauge by id", - []string{"1", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, - false, - &types.GaugeByIDResponse{}, +func TestGetCmdGauges(t *testing.T) { + desc, _ := GetCmdGauges() + tcs := map[string]osmocli.QueryCliTestCase[*types.GaugesRequest]{ + "basic test": { + Cmd: "--offset=2", + ExpectedQuery: &types.GaugesRequest{ + Pagination: &query.PageRequest{Key: []uint8{}, Offset: 2, Limit: 100}, + }, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdGaugeByID() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) - } + osmocli.RunQueryTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestGetCmdActiveGauges() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - }{ - { - "query active gauges", - []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, - false, - &types.ActiveGaugesResponse{}, +func TestGetCmdToDistributeCoins(t *testing.T) { + desc, _ := GetCmdToDistributeCoins() + tcs := map[string]osmocli.QueryCliTestCase[*types.ModuleToDistributeCoinsRequest]{ + "basic test": { + Cmd: "", ExpectedQuery: &types.ModuleToDistributeCoinsRequest{}, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdActiveGauges() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) - } + osmocli.RunQueryTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestGetCmdActiveGaugesPerDenom() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - }{ - { - "query active gauges per denom", - []string{s.cfg.BondDenom, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, - false, - &types.ActiveGaugesPerDenomResponse{}, +func TestGetCmdGaugeByID(t *testing.T) { + desc, _ := GetCmdGaugeByID() + tcs := map[string]osmocli.QueryCliTestCase[*types.GaugeByIDRequest]{ + "basic test": { + Cmd: "1", ExpectedQuery: &types.GaugeByIDRequest{Id: 1}, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdActiveGaugesPerDenom() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) - } + osmocli.RunQueryTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestGetCmdUpcomingGauges() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - }{ - { - "query upcoming gauges", - []string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, - false, - &types.UpcomingGaugesResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdUpcomingGauges() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) +func TestGetCmdActiveGauges(t *testing.T) { + desc, _ := GetCmdActiveGauges() + tcs := map[string]osmocli.QueryCliTestCase[*types.ActiveGaugesRequest]{ + "basic test": { + Cmd: "--offset=2", + ExpectedQuery: &types.ActiveGaugesRequest{ + Pagination: &query.PageRequest{Key: []uint8{}, Offset: 2, Limit: 100}, + }}, } + osmocli.RunQueryTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestGetCmdUpcomingGaugesPerDenom() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - }{ - { - "query upcoming gauges per denom", - []string{s.cfg.BondDenom, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, - false, - &types.UpcomingGaugesPerDenomResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdUpcomingGaugesPerDenom() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) - } +func TestGetCmdActiveGaugesPerDenom(t *testing.T) { + desc, _ := GetCmdActiveGaugesPerDenom() + tcs := map[string]osmocli.QueryCliTestCase[*types.ActiveGaugesPerDenomRequest]{ + "basic test": { + Cmd: "uosmo --offset=2", + ExpectedQuery: &types.ActiveGaugesPerDenomRequest{ + Denom: "uosmo", + Pagination: &query.PageRequest{Key: []uint8{}, Offset: 2, Limit: 100}, + }}, + } + osmocli.RunQueryTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestGetCmdRewardsEst() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - }{ - { - "query rewards estimation by owner", - []string{ - fmt.Sprintf("--%s=%s", cli.FlagOwner, val.Address.String()), - fmt.Sprintf("--%s=100", cli.FlagEndEpoch), - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - }, - false, - &types.RewardsEstResponse{}, - }, - { - "query rewards estimation by lock id", - []string{ - fmt.Sprintf("--%s=1,2", cli.FlagLockIds), - fmt.Sprintf("--%s=100", cli.FlagEndEpoch), - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - }, - false, - &types.RewardsEstResponse{}, - }, - { - "query rewards estimation with empty end epoch", - []string{ - fmt.Sprintf("--%s=1,2", cli.FlagLockIds), - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - }, - false, - &types.RewardsEstResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdRewardsEst() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) +func TestGetCmdUpcomingGauges(t *testing.T) { + desc, _ := GetCmdUpcomingGauges() + tcs := map[string]osmocli.QueryCliTestCase[*types.UpcomingGaugesRequest]{ + "basic test": { + Cmd: "--offset=2", + ExpectedQuery: &types.UpcomingGaugesRequest{ + Pagination: &query.PageRequest{Key: []uint8{}, Offset: 2, Limit: 100}, + }}, } + osmocli.RunQueryTestCases(t, desc, tcs) } -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) +func TestGetCmdUpcomingGaugesPerDenom(t *testing.T) { + desc, _ := GetCmdUpcomingGaugesPerDenom() + tcs := map[string]osmocli.QueryCliTestCase[*types.UpcomingGaugesPerDenomRequest]{ + "basic test": { + Cmd: "uosmo --offset=2", + ExpectedQuery: &types.UpcomingGaugesPerDenomRequest{ + Denom: "uosmo", + Pagination: &query.PageRequest{Key: []uint8{}, Offset: 2, Limit: 100}, + }}, + } + osmocli.RunQueryTestCases(t, desc, tcs) } diff --git a/x/incentives/client/cli/query.go b/x/incentives/client/cli/query.go index 5f67881aac6..b88f2f4abb8 100644 --- a/x/incentives/client/cli/query.go +++ b/x/incentives/client/cli/query.go @@ -21,90 +21,77 @@ import ( func GetQueryCmd() *cobra.Command { // group incentives queries under a subcommand cmd := osmocli.QueryIndexCmd(types.ModuleName) - - cmd.AddCommand( - GetCmdGauges(), - GetCmdToDistributeCoins(), - GetCmdGaugeByID(), - GetCmdActiveGauges(), - GetCmdActiveGaugesPerDenom(), - GetCmdUpcomingGauges(), - GetCmdUpcomingGaugesPerDenom(), - GetCmdRewardsEst(), - ) + qcGetter := types.NewQueryClient + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdGauges) + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdToDistributeCoins) + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdGaugeByID) + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdActiveGauges) + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdActiveGaugesPerDenom) + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdUpcomingGauges) + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdUpcomingGaugesPerDenom) + cmd.AddCommand(GetCmdRewardsEst()) return cmd } // GetCmdGauges returns all available gauges. -func GetCmdGauges() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.GaugesRequest]( - "gauges", - "Query available gauges", - `{{.Short}}`, - types.ModuleName, types.NewQueryClient, - ) +func GetCmdGauges() (*osmocli.QueryDescriptor, *types.GaugesRequest) { + return &osmocli.QueryDescriptor{ + Use: "gauges", + Short: "Query all available gauges", + Long: "{{.Short}}", + }, &types.GaugesRequest{} } // GetCmdToDistributeCoins returns coins that are going to be distributed. -func GetCmdToDistributeCoins() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.ModuleToDistributeCoinsRequest]( - "to-distribute-coins", - "Query coins that is going to be distributed", - `{{.Short}}`, - types.ModuleName, types.NewQueryClient, - ) +func GetCmdToDistributeCoins() (*osmocli.QueryDescriptor, *types.ModuleToDistributeCoinsRequest) { + return &osmocli.QueryDescriptor{ + Use: "to-distribute-coins", + Short: "Query coins that is going to be distributed", + Long: `{{.Short}}`}, &types.ModuleToDistributeCoinsRequest{} } // GetCmdGaugeByID returns a gauge by ID. -func GetCmdGaugeByID() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.GaugeByIDRequest]( - "gauge-by-id [id]", - "Query gauge by id.", - `{{.Short}}{{.ExampleHeader}} +func GetCmdGaugeByID() (*osmocli.QueryDescriptor, *types.GaugeByIDRequest) { + return &osmocli.QueryDescriptor{ + Use: "gauge-by-id [id]", + Short: "Query gauge by id.", + Long: `{{.Short}}{{.ExampleHeader}} {{.CommandPrefix}} gauge-by-id 1 -`, types.ModuleName, types.NewQueryClient) +`}, &types.GaugeByIDRequest{} } // GetCmdActiveGauges returns active gauges. -func GetCmdActiveGauges() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.ActiveGaugesRequest]( - "active-gauges", - "Query active gauges", - `{{.Short}}`, - types.ModuleName, types.NewQueryClient, - ) +func GetCmdActiveGauges() (*osmocli.QueryDescriptor, *types.ActiveGaugesRequest) { + return &osmocli.QueryDescriptor{ + Use: "active-gauges", + Short: "Query active gauges", + Long: `{{.Short}}`}, &types.ActiveGaugesRequest{} } // GetCmdActiveGaugesPerDenom returns active gauges for a specified denom. -func GetCmdActiveGaugesPerDenom() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.ActiveGaugesPerDenomRequest]( - "active-gauges-per-denom [denom]", - "Query active gauges per denom", - `{{.Short}}{{.ExampleHeader}} -{{.CommandPrefix}} active-gauges-per-denom gamm/pool/1`, - types.ModuleName, types.NewQueryClient, - ) +func GetCmdActiveGaugesPerDenom() (*osmocli.QueryDescriptor, *types.ActiveGaugesPerDenomRequest) { + return &osmocli.QueryDescriptor{ + Use: "active-gauges-per-den [den]denom [denom]", + Short: "Query active gauges per denom", + Long: `{{.Short}}{{.ExampleHeader}} +{{.CommandPrefix}} active-gauges-per-denom gamm/pool/1`}, &types.ActiveGaugesPerDenomRequest{} } // GetCmdUpcomingGauges returns scheduled gauges. -func GetCmdUpcomingGauges() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.UpcomingGaugesRequest]( - "upcoming-gauges", - "Query upcoming gauges", - `{{.Short}}`, - types.ModuleName, types.NewQueryClient, - ) +func GetCmdUpcomingGauges() (*osmocli.QueryDescriptor, *types.UpcomingGaugesRequest) { + return &osmocli.QueryDescriptor{ + Use: "upcoming-gauges", + Short: "Query upcoming gauges", + Long: `{{.Short}}`}, &types.UpcomingGaugesRequest{} } // GetCmdUpcomingGaugesPerDenom returns scheduled gauges for specified denom.. -func GetCmdUpcomingGaugesPerDenom() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.UpcomingGaugesPerDenomRequest]( - "upcoming-gauges-per-denom [denom]", - "Query scheduled gauges per denom", - `{{.Short}}`, - types.ModuleName, types.NewQueryClient, - ) +func GetCmdUpcomingGaugesPerDenom() (*osmocli.QueryDescriptor, *types.UpcomingGaugesPerDenomRequest) { + return &osmocli.QueryDescriptor{ + Use: "upcoming-gauges-per-denom [denom]", + Short: "Query scheduled gauges per denom", + Long: `{{.Short}}`}, &types.UpcomingGaugesPerDenomRequest{} } // GetCmdRewardsEst returns rewards estimation. diff --git a/x/lockup/client/cli/cli_test.go b/x/lockup/client/cli/cli_test.go index ff4f41ba781..a8bc958ca98 100644 --- a/x/lockup/client/cli/cli_test.go +++ b/x/lockup/client/cli/cli_test.go @@ -1,740 +1,131 @@ -package cli_test +package cli import ( - "fmt" "testing" "time" - "github.com/gogo/protobuf/proto" - "github.com/stretchr/testify/suite" - tmcli "github.com/tendermint/tendermint/libs/cli" + sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/osmosis-labs/osmosis/v13/app" "github.com/osmosis-labs/osmosis/v13/osmoutils" - "github.com/osmosis-labs/osmosis/v13/x/lockup/client/cli" - lockuptestutil "github.com/osmosis-labs/osmosis/v13/x/lockup/client/testutil" + "github.com/osmosis-labs/osmosis/v13/osmoutils/osmocli" "github.com/osmosis-labs/osmosis/v13/x/lockup/types" - - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/crypto/hd" - "github.com/cosmos/cosmos-sdk/crypto/keyring" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/cosmos/cosmos-sdk/testutil/network" - sdk "github.com/cosmos/cosmos-sdk/types" - banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" ) -type IntegrationTestSuite struct { - suite.Suite - - cfg network.Config - network *network.Network - feeCoins sdk.Coins -} - -func (s *IntegrationTestSuite) SetupSuite() { - s.T().Log("setting up integration test suite") - - s.cfg = app.DefaultConfig() - s.network = network.New(s.T(), s.cfg) - - _, err := s.network.WaitForHeight(1) - s.Require().NoError(err) - - dayLockAmt, err := sdk.ParseCoinNormalized(fmt.Sprintf("200%s", s.network.Config.BondDenom)) - s.Require().NoError(err) - secLockAmt, err := sdk.ParseCoinNormalized(fmt.Sprintf("11%s", s.network.Config.BondDenom)) - s.Require().NoError(err) - thirdLockAmt, err := sdk.ParseCoinNormalized(fmt.Sprintf("12%s", s.network.Config.BondDenom)) - s.Require().NoError(err) - - s.feeCoins = sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))) - - val := s.network.Validators[0] - - // lock tokens for a day - _, err = lockuptestutil.MsgLockTokens(val.ClientCtx, val.Address, dayLockAmt, "24h") - s.Require().NoError(err) - - // lock tokens for a second - _, err = lockuptestutil.MsgLockTokens(val.ClientCtx, val.Address, secLockAmt, "1s") - s.Require().NoError(err) - - // lock tokens for a second - _, err = lockuptestutil.MsgLockTokens(val.ClientCtx, val.Address, thirdLockAmt, "1s") - s.Require().NoError(err) - - // begin unlock all tokens - _, err = lockuptestutil.MsgBeginUnlocking(val.ClientCtx, val.Address) - s.Require().NoError(err) - - _, err = s.network.WaitForHeight(1) - s.Require().NoError(err) -} - -func (s *IntegrationTestSuite) TearDownSuite() { - s.T().Log("tearing down integration test suite") - s.network.Cleanup() -} - -func (s *IntegrationTestSuite) TestNewLockTokensCmd() { - val := s.network.Validators[0] - - info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewValidator", - keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) - s.Require().NoError(err) - - newAddr := sdk.AccAddress(info.GetPubKey().Address()) +var testAddresses = osmoutils.CreateRandomAccounts(3) - _, err = banktestutil.MsgSendExec( - val.ClientCtx, - val.Address, - newAddr, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(20000))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, s.feeCoins.String()), - ) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - expectedCode uint32 - }{ - { - "lock 201stake tokens for 1 day", - []string{ - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(201))).String(), - fmt.Sprintf("--%s=%s", cli.FlagDuration, "24h"), - fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, s.feeCoins.String()), +func TestLockTokensCmd(t *testing.T) { + desc, _ := NewLockTokensCmd() + tcs := map[string]osmocli.TxCliTestCase[*types.MsgLockTokens]{ + "lock 201stake tokens for 1 day": { + Cmd: "201uosmo --duration=24h --from=" + testAddresses[0].String(), + ExpectedMsg: &types.MsgLockTokens{ + Owner: testAddresses[0].String(), + Duration: time.Hour * 24, + Coins: sdk.NewCoins(sdk.NewInt64Coin("uosmo", 201)), }, - false, &sdk.TxResponse{}, 0, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewLockTokensCmd() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } + osmocli.RunTxTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestBeginUnlockingCmd() { - val := s.network.Validators[0] - - info, _, err := val.ClientCtx.Keyring.NewMnemonic("BeginUnlockingAcc", - keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) - s.Require().NoError(err) - - newAddr := sdk.AccAddress(info.GetPubKey().Address()) - - _, err = banktestutil.MsgSendExec( - val.ClientCtx, - val.Address, - newAddr, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(20000))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - osmoutils.DefaultFeeString(s.cfg), - ) - s.Require().NoError(err) - - // lock tokens for a second - _, err = lockuptestutil.MsgLockTokens(val.ClientCtx, newAddr, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), "1s") - s.Require().NoError(err) - - _, err = s.network.WaitForHeight(1) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - expectedCode uint32 - }{ - { - "begin unlocking", - []string{ - fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, s.feeCoins.String()), +func TestBeginUnlockingAllCmd(t *testing.T) { + desc, _ := NewBeginUnlockingAllCmd() + tcs := map[string]osmocli.TxCliTestCase[*types.MsgBeginUnlockingAll]{ + "basic test": { + Cmd: "--from=" + testAddresses[0].String(), + ExpectedMsg: &types.MsgBeginUnlockingAll{ + Owner: testAddresses[0].String(), }, - false, &sdk.TxResponse{}, 0, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewBeginUnlockingAllCmd() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } + osmocli.RunTxTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestNewBeginUnlockPeriodLockCmd() { - val := s.network.Validators[0] - clientCtx := val.ClientCtx - - info, _, err := val.ClientCtx.Keyring.NewMnemonic("BeginUnlockPeriodLockAcc", - keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) - s.Require().NoError(err) - - newAddr := sdk.AccAddress(info.GetPubKey().Address()) - - _, err = banktestutil.MsgSendExec( - clientCtx, - val.Address, - newAddr, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(20000))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - osmoutils.DefaultFeeString(s.cfg), - ) - s.Require().NoError(err) - - // lock tokens for a second - txResp := sdk.TxResponse{} - out, err := lockuptestutil.MsgLockTokens(clientCtx, - newAddr, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))), - "1s") - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) - // This is a hardcoded path in the events to get the lockID - // this is incredibly brittle... - // fmt.Println(txResp.Logs[0]) - lockID := txResp.Logs[0].Events[2].Attributes[0].Value - - _, err = s.network.WaitForHeight(1) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - expectedCode uint32 - }{ - { - "begin unlocking by id", - []string{ - lockID, - fmt.Sprintf("--%s=%s", cli.FlagAmount, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(100))).String()), - fmt.Sprintf("--%s=%s", flags.FlagFrom, newAddr), - // common args - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, s.feeCoins.String()), +func TestBeginUnlockingByIDCmd(t *testing.T) { + desc, _ := NewBeginUnlockByIDCmd() + tcs := map[string]osmocli.TxCliTestCase[*types.MsgBeginUnlocking]{ + "basic test no coins": { + Cmd: "10 --from=" + testAddresses[0].String(), + ExpectedMsg: &types.MsgBeginUnlocking{ + Owner: testAddresses[0].String(), + ID: 10, + Coins: sdk.Coins(nil), }, - false, &sdk.TxResponse{}, 0, }, - } - fmt.Println(testCases[0].args) - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.NewBeginUnlockByIDCmd() - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - - txResp := tc.respType.(*sdk.TxResponse) - s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) - } - }) - } -} - -func (s *IntegrationTestSuite) TestCmdAccountUnlockableCoins() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - coins sdk.Coins - }{ - { - "query validator account unlockable coins", - []string{ - val.Address.String(), - fmt.Sprintf("--%s=json", tmcli.OutputFlag), + "basic test w/ coins": { + Cmd: "10 --amount=5uosmo --from=" + testAddresses[0].String(), + ExpectedMsg: &types.MsgBeginUnlocking{ + Owner: testAddresses[0].String(), + ID: 10, + Coins: sdk.NewCoins(sdk.NewInt64Coin("uosmo", 5)), }, - sdk.Coins{}, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdAccountUnlockableCoins() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.AccountUnlockableCoinsResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Equal(tc.coins.String(), result.Coins.String()) - }) - } + osmocli.RunTxTestCases(t, desc, tcs) } -func (s *IntegrationTestSuite) TestCmdAccountUnlockingCoins() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - coins sdk.Coins - }{ - { - "query validator account unlocking coins", - []string{ - val.Address.String(), - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - }, - sdk.Coins{sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))}, +func TestModuleBalanceCmd(t *testing.T) { + desc, _ := GetCmdModuleBalance() + tcs := map[string]osmocli.QueryCliTestCase[*types.ModuleBalanceRequest]{ + "basic test": { + Cmd: "", + ExpectedQuery: &types.ModuleBalanceRequest{}, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdAccountUnlockingCoins() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.AccountUnlockingCoinsResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Equal(tc.coins.String(), result.Coins.String()) - }) - } + osmocli.RunQueryTestCases(t, desc, tcs) } -func (s IntegrationTestSuite) TestCmdModuleBalance() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - coins sdk.Coins - }{ - { - "query module balance", - []string{ - fmt.Sprintf("--%s=json", tmcli.OutputFlag), +func TestAccountUnlockingCoinsCmd(t *testing.T) { + desc, _ := GetCmdAccountUnlockingCoins() + tcs := map[string]osmocli.QueryCliTestCase[*types.AccountUnlockingCoinsRequest]{ + "basic test": { + Cmd: testAddresses[0].String(), + ExpectedQuery: &types.AccountUnlockingCoinsRequest{ + Owner: testAddresses[0].String(), }, - sdk.Coins{sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(400))}, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdModuleBalance() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.ModuleBalanceResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Equal(tc.coins.String(), result.Coins.String()) - }) - } + osmocli.RunQueryTestCases(t, desc, tcs) } -func (s IntegrationTestSuite) TestCmdModuleLockedAmount() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - coins sdk.Coins - }{ - { - "query module locked balance", - []string{ - fmt.Sprintf("--%s=json", tmcli.OutputFlag), +func TestCmdAccountLockedPastTime(t *testing.T) { + desc, _ := GetCmdAccountLockedPastTime() + tcs := map[string]osmocli.QueryCliTestCase[*types.AccountLockedPastTimeRequest]{ + "basic test": { + Cmd: testAddresses[0].String() + " 1670431012", + ExpectedQuery: &types.AccountLockedPastTimeRequest{ + Owner: testAddresses[0].String(), + Timestamp: time.Unix(1670431012, 0), }, - sdk.Coins{sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(400))}, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdModuleLockedAmount() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.ModuleLockedAmountResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Equal(tc.coins.String(), result.Coins.String()) - }) - } + osmocli.RunQueryTestCases(t, desc, tcs) } -func (s IntegrationTestSuite) TestCmdAccountLockedCoins() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - coins sdk.Coins - }{ - { - "query account locked coins", - []string{ - val.Address.String(), - fmt.Sprintf("--%s=json", tmcli.OutputFlag), +func TestCmdAccountLockedPastTimeNotUnlockingOnly(t *testing.T) { + desc, _ := GetCmdAccountLockedPastTimeNotUnlockingOnly() + tcs := map[string]osmocli.QueryCliTestCase[*types.AccountLockedPastTimeNotUnlockingOnlyRequest]{ + "basic test": { + Cmd: testAddresses[0].String() + " 1670431012", + ExpectedQuery: &types.AccountLockedPastTimeNotUnlockingOnlyRequest{ + Owner: testAddresses[0].String(), + Timestamp: time.Unix(1670431012, 0), }, - sdk.Coins{sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(200))}, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdAccountLockedCoins() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.ModuleLockedAmountResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Equal(tc.coins.String(), result.Coins.String()) - }) - } + osmocli.RunQueryTestCases(t, desc, tcs) } -func (s IntegrationTestSuite) TestCmdAccountLockedPastTime() { - val := s.network.Validators[0] - - timestamp := time.Now().Unix() - testCases := []struct { - name string - args []string - }{ - { - "query account locked coins past time", - []string{ - val.Address.String(), - fmt.Sprintf("%d", timestamp), - fmt.Sprintf("--%s=json", tmcli.OutputFlag), +func TestCmdTotalLockedByDenom(t *testing.T) { + desc, _ := GetCmdTotalLockedByDenom() + tcs := map[string]osmocli.QueryCliTestCase[*types.LockedDenomRequest]{ + "basic test": { + Cmd: "uosmo --min-duration=1s", + ExpectedQuery: &types.LockedDenomRequest{ + Denom: "uosmo", + Duration: time.Second, }, }, } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdAccountLockedPastTime() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.AccountLockedPastTimeResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Len(result.Locks, 1) - }) - } -} - -func (s IntegrationTestSuite) TestCmdAccountLockedPastTimeNotUnlockingOnly() { - val := s.network.Validators[0] - - timestamp := time.Now().Unix() - testCases := []struct { - name string - args []string - }{ - { - "query account locked coins past time not unlocking only", - []string{ - val.Address.String(), - fmt.Sprintf("%d", timestamp), - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - }, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdAccountLockedPastTimeNotUnlockingOnly() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.AccountLockedPastTimeNotUnlockingOnlyResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Len(result.Locks, 0) - }) - } -} - -func (s IntegrationTestSuite) TestCmdAccountUnlockedBeforeTime() { - val := s.network.Validators[0] - - timestamp := time.Now().Unix() - testCases := []struct { - name string - args []string - }{ - { - "query account locked coins before time", - []string{ - val.Address.String(), - fmt.Sprintf("%d", timestamp), - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - }, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdAccountUnlockedBeforeTime() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.AccountUnlockedBeforeTimeResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Len(result.Locks, 0) - }) - } -} - -func (s IntegrationTestSuite) TestCmdAccountLockedPastTimeDenom() { - val := s.network.Validators[0] - - timestamp := time.Now().Unix() - testCases := []struct { - name string - args []string - }{ - { - "query account locked coins past time denom", - []string{ - val.Address.String(), - fmt.Sprintf("%d", timestamp), - s.cfg.BondDenom, - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - }, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdAccountLockedPastTimeDenom() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.AccountLockedPastTimeDenomResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Len(result.Locks, 1) - }) - } -} - -func (s IntegrationTestSuite) TestCmdLockedByID() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - }{ - { - "get lock by id", - []string{ - fmt.Sprintf("%d", 1), - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - }, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdLockedByID() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.LockedResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Equal(result.Lock.ID, uint64(1)) - }) - } -} - -func (s IntegrationTestSuite) TestCmdAccountLockedLongerDuration() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - }{ - { - "get account locked longer than duration", - []string{ - val.Address.String(), - "1s", - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - }, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdAccountLockedLongerDuration() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.AccountLockedLongerDurationResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Len(result.Locks, 1) - }) - } -} - -func (s IntegrationTestSuite) TestCmdAccountLockedLongerDurationNotUnlockingOnly() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - }{ - { - "get account locked longer than duration not unlocking only", - []string{ - val.Address.String(), - "1s", - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - }, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdAccountLockedLongerDurationNotUnlockingOnly() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.AccountLockedLongerDurationNotUnlockingOnlyResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Len(result.Locks, 0) - }) - } -} - -func (s IntegrationTestSuite) TestCmdAccountLockedLongerDurationDenom() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - }{ - { - "get account locked longer than duration denom", - []string{ - val.Address.String(), - "1s", - s.cfg.BondDenom, - fmt.Sprintf("--%s=json", tmcli.OutputFlag), - }, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdAccountLockedLongerDurationDenom() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - - var result types.AccountLockedLongerDurationDenomResponse - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &result)) - s.Require().Len(result.Locks, 1) - }) - } -} - -func TestIntegrationTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) + osmocli.RunQueryTestCases(t, desc, tcs) } diff --git a/x/lockup/client/cli/query.go b/x/lockup/client/cli/query.go index 907638404f8..62b8dd2e72a 100644 --- a/x/lockup/client/cli/query.go +++ b/x/lockup/client/cli/query.go @@ -9,6 +9,7 @@ import ( "time" "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -24,21 +25,22 @@ import ( func GetQueryCmd() *cobra.Command { cmd := osmocli.QueryIndexCmd(types.ModuleName) + qcGetter := types.NewQueryClient + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdModuleBalance) + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdModuleLockedAmount) + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdAccountUnlockingCoins) + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdAccountLockedPastTime) + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdAccountLockedPastTimeNotUnlockingOnly) + osmocli.AddQueryCmd(cmd, qcGetter, GetCmdTotalLockedByDenom) cmd.AddCommand( - GetCmdModuleBalance(), - GetCmdModuleLockedAmount(), GetCmdAccountUnlockableCoins(), - GetCmdAccountUnlockingCoins(), GetCmdAccountLockedCoins(), - GetCmdAccountLockedPastTime(), - GetCmdAccountLockedPastTimeNotUnlockingOnly(), GetCmdAccountUnlockedBeforeTime(), GetCmdAccountLockedPastTimeDenom(), GetCmdLockedByID(), GetCmdAccountLockedLongerDuration(), GetCmdAccountLockedLongerDurationNotUnlockingOnly(), GetCmdAccountLockedLongerDurationDenom(), - GetCmdTotalLockedByDenom(), GetCmdOutputLocksJson(), GetCmdSyntheticLockupsByLockupID(), GetCmdAccountLockedDuration(), @@ -52,20 +54,20 @@ func GetQueryCmd() *cobra.Command { // GetCmdModuleBalance returns full balance of the lockup module. // Lockup module is where coins of locks are held. // This includes locked balance and unlocked balance of the module. -func GetCmdModuleBalance() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.ModuleBalanceRequest]( - "module-balance", - "Query module balance", - `{{.Short}}`, types.ModuleName, types.NewQueryClient) +func GetCmdModuleBalance() (*osmocli.QueryDescriptor, *types.ModuleBalanceRequest) { + return &osmocli.QueryDescriptor{ + Use: "module-balance", + Short: "Query module balance", + Long: `{{.Short}}`}, &types.ModuleBalanceRequest{} } // GetCmdModuleLockedAmount returns locked balance of the module, // which are all the tokens not unlocking + tokens that are not finished unlocking. -func GetCmdModuleLockedAmount() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.ModuleLockedAmountRequest]( - "module-locked-amount", - "Query locked amount", - `{{.Short}}`, types.ModuleName, types.NewQueryClient) +func GetCmdModuleLockedAmount() (*osmocli.QueryDescriptor, *types.ModuleLockedAmountRequest) { + return &osmocli.QueryDescriptor{ + Use: "module-locked-amount", + Short: "Query locked amount", + Long: `{{.Short}}`}, &types.ModuleLockedAmountRequest{} } // GetCmdAccountUnlockableCoins returns unlockable coins which has finsihed unlocking. @@ -107,13 +109,12 @@ $ %s query lockup account-unlockable-coins
} // GetCmdAccountUnlockingCoins returns unlocking coins of a specific account. -func GetCmdAccountUnlockingCoins() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.AccountUnlockingCoinsRequest]( - "account-unlocking-coins
", - "Query account's unlocking coins", - `{{.Short}}{{.ExampleHeader}} -{{.CommandPrefix}} account-unlocking-coins
-`, types.ModuleName, types.NewQueryClient) +func GetCmdAccountUnlockingCoins() (*osmocli.QueryDescriptor, *types.AccountUnlockingCoinsRequest) { + return &osmocli.QueryDescriptor{ + Use: "account-unlocking-coins
", + Short: "Query account's unlocking coins", + Long: `{{.Short}}{{.ExampleHeader}} +{{.CommandPrefix}} account-unlocking-coins
`}, &types.AccountUnlockingCoinsRequest{} } // GetCmdAccountLockedCoins returns locked coins that that are still in a locked state from the specified account. @@ -127,25 +128,25 @@ func GetCmdAccountLockedCoins() *cobra.Command { } // GetCmdAccountLockedPastTime returns locks of an account with unlock time beyond timestamp. -func GetCmdAccountLockedPastTime() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.AccountLockedPastTimeRequest]( - "account-locked-pastime
", - "Query locked records of an account with unlock time beyond timestamp", - `{{.Short}}{{.ExampleHeader}} +func GetCmdAccountLockedPastTime() (*osmocli.QueryDescriptor, *types.AccountLockedPastTimeRequest) { + return &osmocli.QueryDescriptor{ + Use: "account-locked-pastime
", + Short: "Query locked records of an account with unlock time beyond timestamp", + Long: `{{.Short}}{{.ExampleHeader}} {{.CommandPrefix}} account-locked-pastime
-`, types.ModuleName, types.NewQueryClient) +`}, &types.AccountLockedPastTimeRequest{} } // GetCmdAccountLockedPastTimeNotUnlockingOnly returns locks of an account with unlock time beyond provided timestamp // amongst the locks that are in the unlocking queue. -func GetCmdAccountLockedPastTimeNotUnlockingOnly() *cobra.Command { - return osmocli.SimpleQueryCmd[*types.AccountLockedPastTimeNotUnlockingOnlyRequest]( - "account-locked-pastime-not-unlocking
", - "Query locked records of an account with unlock time beyond timestamp within not unlocking queue.", - `{{.Short}} +func GetCmdAccountLockedPastTimeNotUnlockingOnly() (*osmocli.QueryDescriptor, *types.AccountLockedPastTimeNotUnlockingOnlyRequest) { + return &osmocli.QueryDescriptor{ + Use: "account-locked-pastime-not-unlocking
", + Short: "Query locked records of an account with unlock time beyond timestamp within not unlocking queue.", + Long: `{{.Short}} Timestamp is UNIX time in seconds.{{.ExampleHeader}} {{.CommandPrefix}} account-locked-pastime-not-unlocking
-`, types.ModuleName, types.NewQueryClient) +`}, &types.AccountLockedPastTimeNotUnlockingOnlyRequest{} } // GetCmdAccountUnlockedBeforeTime returns locks with unlock time before the provided timestamp. @@ -181,7 +182,7 @@ func GetCmdLockedByID() *cobra.Command { QueryFnName: "LockedByID", } q.Long = osmocli.FormatLongDesc(q.Long, osmocli.NewLongMetadata(types.ModuleName).WithShort(q.Short)) - return osmocli.SimpleQueryFromDescriptor[*types.LockedRequest](q, types.NewQueryClient) + return osmocli.BuildQueryCli[*types.LockedRequest](&q, types.NewQueryClient) } // GetCmdSyntheticLockupsByLockupID returns synthetic lockups by lockup id. @@ -226,8 +227,8 @@ func GetCmdAccountLockedLongerDurationDenom() *cobra.Command { `{{.Short}}`, types.ModuleName, types.NewQueryClient) } -func GetCmdTotalLockedByDenom() *cobra.Command { - cmd := osmocli.SimpleQueryFromDescriptor[*types.LockedDenomRequest](osmocli.QueryDescriptor{ +func GetCmdTotalLockedByDenom() (*osmocli.QueryDescriptor, *types.LockedDenomRequest) { + return &osmocli.QueryDescriptor{ Use: "total-locked-of-denom ", Short: "Query locked amount for a specific denom bigger then duration provided", Long: osmocli.FormatLongDescDirect(`{{.Short}}{{.ExampleHeader}} @@ -235,11 +236,8 @@ func GetCmdTotalLockedByDenom() *cobra.Command { CustomFlagOverrides: map[string]string{ "duration": FlagMinDuration, }, - QueryFnName: "LockedDenom", - }, types.NewQueryClient) - - cmd.Flags().AddFlagSet(FlagSetMinDuration()) - return cmd + Flags: osmocli.FlagDesc{OptionalFlags: []*pflag.FlagSet{FlagSetMinDuration()}}, + }, &types.LockedDenomRequest{} } // GetCmdOutputLocksJson outputs all locks into a file called lock_export.json. diff --git a/x/lockup/client/cli/query_test.go b/x/lockup/client/cli/query_test.go deleted file mode 100644 index d04f510ea87..00000000000 --- a/x/lockup/client/cli/query_test.go +++ /dev/null @@ -1,152 +0,0 @@ -package cli_test - -import ( - gocontext "context" - "testing" - "time" - - "github.com/stretchr/testify/suite" - - "github.com/osmosis-labs/osmosis/v13/app/apptesting" - "github.com/osmosis-labs/osmosis/v13/x/lockup/types" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -type QueryTestSuite struct { - apptesting.KeeperTestHelper - queryClient types.QueryClient -} - -func (s *QueryTestSuite) SetupSuite() { - s.Setup() - s.queryClient = types.NewQueryClient(s.QueryHelper) - - // create a pool - s.PrepareBalancerPool() - // set up lock with id = 1 - s.LockTokens(s.TestAccs[0], sdk.Coins{sdk.NewCoin("gamm/pool/1", sdk.NewInt(1000000))}, time.Hour*24) - - s.Commit() -} - -func (s *QueryTestSuite) TestQueriesNeverAlterState() { - testCases := []struct { - name string - query string - input interface{} - output interface{} - }{ - { - "Query account locked coins", - "/osmosis.lockup.Query/AccountLockedCoins", - &types.AccountLockedCoinsRequest{Owner: s.TestAccs[0].String()}, - &types.AccountLockedCoinsResponse{}, - }, - { - "Query account locked by duration", - "/osmosis.lockup.Query/AccountLockedDuration", - &types.AccountLockedDurationRequest{Owner: s.TestAccs[0].String(), Duration: time.Hour * 24}, - &types.AccountLockedDurationResponse{}, - }, - { - "Query account locked longer than given duration", - "/osmosis.lockup.Query/AccountLockedLongerDuration", - &types.AccountLockedLongerDurationRequest{Owner: s.TestAccs[0].String(), Duration: time.Hour}, - &types.AccountLockedLongerDurationResponse{}, - }, - { - "Query account locked by denom that longer than given duration", - "/osmosis.lockup.Query/AccountLockedLongerDurationDenom", - &types.AccountLockedLongerDurationDenomRequest{Owner: s.TestAccs[0].String(), Duration: time.Hour, Denom: "gamm/pool/1"}, - &types.AccountLockedLongerDurationDenomResponse{}, - }, - { - "Query account locked longer than given duration not unlocking", - "/osmosis.lockup.Query/AccountLockedLongerDurationNotUnlockingOnly", - &types.AccountLockedLongerDurationNotUnlockingOnlyRequest{Owner: s.TestAccs[0].String(), Duration: time.Hour}, - &types.AccountLockedLongerDurationNotUnlockingOnlyResponse{}, - }, - { - "Query account locked in past time", - "/osmosis.lockup.Query/AccountLockedPastTime", - &types.AccountLockedPastTimeRequest{Owner: s.TestAccs[0].String()}, - &types.AccountLockedPastTimeResponse{}, - }, - { - "Query account locked in past time by denom", - "/osmosis.lockup.Query/AccountLockedPastTimeDenom", - &types.AccountLockedPastTimeDenomRequest{Owner: s.TestAccs[0].String(), Denom: "gamm/pool/1"}, - &types.AccountLockedPastTimeDenomResponse{}, - }, - { - " Query account locked in past time that not unlocking", - "/osmosis.lockup.Query/AccountLockedPastTimeNotUnlockingOnly", - &types.AccountLockedPastTimeNotUnlockingOnlyRequest{Owner: s.TestAccs[0].String()}, - &types.AccountLockedPastTimeNotUnlockingOnlyResponse{}, - }, - { - "Query account unlockable coins", - "/osmosis.lockup.Query/AccountUnlockableCoins", - &types.AccountUnlockableCoinsRequest{Owner: s.TestAccs[0].String()}, - &types.AccountUnlockableCoinsResponse{}, - }, - { - "Query account unlocked before given time", - "/osmosis.lockup.Query/AccountUnlockedBeforeTime", - &types.AccountUnlockedBeforeTimeRequest{Owner: s.TestAccs[0].String()}, - &types.AccountUnlockedBeforeTimeResponse{}, - }, - { - "Query account unlocking coins", - "/osmosis.lockup.Query/AccountUnlockingCoins", - &types.AccountUnlockingCoinsRequest{Owner: s.TestAccs[0].String()}, - &types.AccountUnlockingCoinsResponse{}, - }, - { - "Query lock by id", - "/osmosis.lockup.Query/LockedByID", - &types.LockedRequest{LockId: 1}, - &types.LockedResponse{}, - }, - { - "Query lock by denom", - "/osmosis.lockup.Query/LockedDenom", - &types.LockedDenomRequest{Duration: time.Hour * 24, Denom: "gamm/pool/1"}, - &types.LockedDenomResponse{}, - }, - { - "Query module balances", - "/osmosis.lockup.Query/ModuleBalance", - &types.ModuleBalanceRequest{}, - &types.ModuleBalanceResponse{}, - }, - { - "Query module locked amount", - "/osmosis.lockup.Query/ModuleLockedAmount", - &types.ModuleLockedAmountRequest{}, - &types.ModuleLockedAmountResponse{}, - }, - { - "Query synthetic lock by id", - "/osmosis.lockup.Query/SyntheticLockupsByLockupID", - &types.SyntheticLockupsByLockupIDRequest{LockId: 1}, - &types.SyntheticLockupsByLockupIDResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - s.SetupSuite() - err := s.QueryHelper.Invoke(gocontext.Background(), tc.query, tc.input, tc.output) - s.Require().NoError(err) - s.StateNotAltered() - }) - } -} - -func TestQueryTestSuite(t *testing.T) { - suite.Run(t, new(QueryTestSuite)) -} diff --git a/x/lockup/client/cli/tx.go b/x/lockup/client/cli/tx.go index cc4aa43354d..bd1df6746ea 100644 --- a/x/lockup/client/cli/tx.go +++ b/x/lockup/client/cli/tx.go @@ -11,50 +11,48 @@ import ( // GetTxCmd returns the transaction commands for this module. func GetTxCmd() *cobra.Command { cmd := osmocli.TxIndexCmd(types.ModuleName) - cmd.AddCommand( - NewLockTokensCmd(), - NewBeginUnlockingAllCmd(), - NewBeginUnlockByIDCmd(), - NewForceUnlockByIdCmd(), - ) + osmocli.AddTxCmd(cmd, NewLockTokensCmd) + osmocli.AddTxCmd(cmd, NewBeginUnlockingAllCmd) + osmocli.AddTxCmd(cmd, NewBeginUnlockByIDCmd) + osmocli.AddTxCmd(cmd, NewForceUnlockByIdCmd) return cmd } -func NewLockTokensCmd() *cobra.Command { - return osmocli.BuildTxCli[*types.MsgLockTokens](&osmocli.TxCliDesc{ +func NewLockTokensCmd() (*osmocli.TxCliDesc, *types.MsgLockTokens) { + return &osmocli.TxCliDesc{ Use: "lock-tokens [tokens]", Short: "lock tokens into lockup pool from user account", CustomFlagOverrides: map[string]string{ "duration": FlagDuration, }, Flags: osmocli.FlagDesc{RequiredFlags: []*pflag.FlagSet{FlagSetLockTokens()}}, - }) + }, &types.MsgLockTokens{} } // TODO: We should change the Use string to be unlock-all -func NewBeginUnlockingAllCmd() *cobra.Command { - return osmocli.BuildTxCli[*types.MsgBeginUnlockingAll](&osmocli.TxCliDesc{ +func NewBeginUnlockingAllCmd() (*osmocli.TxCliDesc, *types.MsgBeginUnlockingAll) { + return &osmocli.TxCliDesc{ Use: "begin-unlock-tokens", Short: "begin unlock not unlocking tokens from lockup pool for sender", - }) + }, &types.MsgBeginUnlockingAll{} } // NewBeginUnlockByIDCmd unlocks individual period lock by ID. -func NewBeginUnlockByIDCmd() *cobra.Command { - return osmocli.BuildTxCli[*types.MsgBeginUnlocking](&osmocli.TxCliDesc{ +func NewBeginUnlockByIDCmd() (*osmocli.TxCliDesc, *types.MsgBeginUnlocking) { + return &osmocli.TxCliDesc{ Use: "begin-unlock-by-id [id]", Short: "begin unlock individual period lock by ID", CustomFlagOverrides: map[string]string{ "coins": FlagAmount, }, Flags: osmocli.FlagDesc{OptionalFlags: []*pflag.FlagSet{FlagSetUnlockTokens()}}, - }) + }, &types.MsgBeginUnlocking{} } // NewForceUnlockByIdCmd force unlocks individual period lock by ID if proper permissions exist. -func NewForceUnlockByIdCmd() *cobra.Command { - return osmocli.BuildTxCli[*types.MsgBeginUnlocking](&osmocli.TxCliDesc{ +func NewForceUnlockByIdCmd() (*osmocli.TxCliDesc, *types.MsgForceUnlock) { + return &osmocli.TxCliDesc{ Use: "force-unlock-by-id [id]", Short: "force unlocks individual period lock by ID", Long: "force unlocks individual period lock by ID. if no amount provided, entire lock is unlocked", @@ -62,5 +60,5 @@ func NewForceUnlockByIdCmd() *cobra.Command { "coins": FlagAmount, }, Flags: osmocli.FlagDesc{OptionalFlags: []*pflag.FlagSet{FlagSetUnlockTokens()}}, - }) + }, &types.MsgForceUnlock{} } diff --git a/x/lockup/client/testutil/test_helpers.go b/x/lockup/client/testutil/test_helpers.go deleted file mode 100644 index 90a3d0f3f7b..00000000000 --- a/x/lockup/client/testutil/test_helpers.go +++ /dev/null @@ -1,43 +0,0 @@ -package testutil - -import ( - "fmt" - - lockupcli "github.com/osmosis-labs/osmosis/v13/x/lockup/client/cli" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/testutil" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// commonArgs is args for CLI test commands. -var commonArgs = []string{ - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))).String()), -} - -// MsgLockTokens creates a lock tokens message. -func MsgLockTokens(clientCtx client.Context, owner fmt.Stringer, amount fmt.Stringer, duration string, extraArgs ...string) (testutil.BufferWriter, error) { - args := []string{ - amount.String(), - fmt.Sprintf("--%s=%s", lockupcli.FlagDuration, duration), - fmt.Sprintf("--%s=%s", flags.FlagFrom, owner.String()), - } - - args = append(args, commonArgs...) - return clitestutil.ExecTestCLICmd(clientCtx, lockupcli.NewLockTokensCmd(), args) -} - -// MsgBeginUnlocking creates a begin unlock tokens message. -func MsgBeginUnlocking(clientCtx client.Context, owner fmt.Stringer, extraArgs ...string) (testutil.BufferWriter, error) { - args := []string{ - fmt.Sprintf("--%s=%s", flags.FlagFrom, owner.String()), - fmt.Sprintf("--%s=%d", flags.FlagGas, 500000), - } - - args = append(args, commonArgs...) - return clitestutil.ExecTestCLICmd(clientCtx, lockupcli.NewBeginUnlockingAllCmd(), args) -} diff --git a/x/pool-incentives/client/cli/cli_test.go b/x/pool-incentives/client/cli/cli_test.go deleted file mode 100644 index d0333ba9d77..00000000000 --- a/x/pool-incentives/client/cli/cli_test.go +++ /dev/null @@ -1,213 +0,0 @@ -package cli_test - -import ( - "github.com/gogo/protobuf/proto" - "github.com/stretchr/testify/suite" - - "github.com/osmosis-labs/osmosis/v13/app" - "github.com/osmosis-labs/osmosis/v13/x/pool-incentives/client/cli" - "github.com/osmosis-labs/osmosis/v13/x/pool-incentives/types" - - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/cosmos/cosmos-sdk/testutil/network" -) - -type IntegrationTestSuite struct { - suite.Suite - - cfg network.Config - network *network.Network -} - -// SetupSuite sets up an integration test suite. -func (s *IntegrationTestSuite) SetupSuite() { - s.T().Log("setting up integration test suite") - - s.cfg = app.DefaultConfig() - - s.network = network.New(s.T(), s.cfg) - - _, err := s.network.WaitForHeight(1) - s.Require().NoError(err) -} - -// TearDownSuite tears down the integration test suite. -func (s *IntegrationTestSuite) TearDownSuite() { - s.T().Log("tearing down integration test suite") - s.network.Cleanup() -} - -// TestGetCmdGaugeIds tests gaugeID CLI query commands -func (s *IntegrationTestSuite) TestGetCmdGaugeIds() { - val := s.network.Validators[0] - - testCases := []struct { - name string - expectErr bool - respType proto.Message - }{ - { - "query gauge-ids", - false, &types.QueryGaugeIdsResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdGaugeIds() - clientCtx := val.ClientCtx - - args := []string{"1"} - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) - } -} - -// TestGetCmdDistrInfo tests distribution info CLI query commands -func (s *IntegrationTestSuite) TestGetCmdDistrInfo() { - val := s.network.Validators[0] - - testCases := []struct { - name string - expectErr bool - respType proto.Message - }{ - { - "query distr-info", - false, &types.QueryDistrInfoResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdDistrInfo() - clientCtx := val.ClientCtx - - args := []string{} - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) - } -} - -// TestGetCmdLockableDurations tests lockable duration CLI query commands -func (s *IntegrationTestSuite) TestGetCmdLockableDurations() { - val := s.network.Validators[0] - - testCases := []struct { - name string - expectErr bool - respType proto.Message - }{ - { - "query lockable durations", - false, &types.QueryLockableDurationsResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdLockableDurations() - clientCtx := val.ClientCtx - - args := []string{} - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) - } -} - -// TestGetCmdIncentivizedPools tests incentivized pools CLI query commands -func (s *IntegrationTestSuite) TestGetCmdIncentivizedPools() { - val := s.network.Validators[0] - - testCases := []struct { - name string - expectErr bool - respType proto.Message - }{ - { - "query incentivized pools", - false, &types.QueryIncentivizedPoolsResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdIncentivizedPools() - clientCtx := val.ClientCtx - - args := []string{} - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) - } -} - -// TestGetCmdExternalIncentiveGauges tests incentivized pools CLI query commands -func (s *IntegrationTestSuite) TestGetCmdExternalIncentiveGauges() { - val := s.network.Validators[0] - - testCases := []struct { - name string - expectErr bool - respType proto.Message - }{ - { - "query external incentivized pools", - false, &types.QueryExternalIncentiveGaugesResponse{}, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdExternalIncentiveGauges() - clientCtx := val.ClientCtx - - args := []string{} - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err, out.String()) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) - } - }) - } -}