diff --git a/tests/Makefile b/tests/Makefile index d992d555..0349dfc1 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,4 +1,5 @@ test-integration: + go test -mod=readonly ./integration/... -test.v -timeout 10m test-e2e: go test ./e2e/... -mod=readonly -test.v -timeout 10m diff --git a/tests/e2e/auction/grpc.go b/tests/e2e/auction/grpc.go index 332bc103..0491698b 100644 --- a/tests/e2e/auction/grpc.go +++ b/tests/e2e/auction/grpc.go @@ -8,6 +8,12 @@ import ( auctiontypes "git.vdb.to/cerc-io/laconic2d/x/auction" ) +const ( + randomAuctionID = "randomAuctionID" + randomBidderAddress = "randomBidderAddress" + randomOwnerAddress = "randomOwnerAddress" +) + func (ets *E2ETestSuite) TestQueryParamsGrpc() { val := ets.network.Validators[0] sr := ets.Require() @@ -24,3 +30,43 @@ func (ets *E2ETestSuite) TestQueryParamsGrpc() { sr.Equal(*params.GetParams(), auctiontypes.DefaultParams()) }) } + +func (ets *E2ETestSuite) TestGetAllAuctionsGrpc() { + val := ets.network.Validators[0] + sr := ets.Require() + reqURL := fmt.Sprintf("%s/cerc/auction/v1/auctions", val.APIAddress) + + testCases := []struct { + msg string + url string + errorMsg string + isErrorExpected bool + }{ + { + "invalid request to get all auctions", + reqURL + randomAuctionID, + "", + true, + }, + { + "valid request to get all auctions", + reqURL, + "", + false, + }, + } + for _, tc := range testCases { + ets.Run(tc.msg, func() { + resp, err := testutil.GetRequest(tc.url) + if tc.isErrorExpected { + sr.Contains(string(resp), tc.errorMsg) + } else { + sr.NoError(err) + var auctions auctiontypes.QueryAuctionsResponse + err = val.ClientCtx.Codec.UnmarshalJSON(resp, &auctions) + sr.NoError(err) + sr.NotZero(len(auctions.Auctions.Auctions)) + } + }) + } +} diff --git a/tests/e2e/auction/query.go b/tests/e2e/auction/query.go new file mode 100644 index 00000000..fcca2de1 --- /dev/null +++ b/tests/e2e/auction/query.go @@ -0,0 +1,45 @@ +package auction + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/client/flags" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + + types "git.vdb.to/cerc-io/laconic2d/x/auction" + "git.vdb.to/cerc-io/laconic2d/x/auction/client/cli" +) + +var queryJSONFlag = []string{fmt.Sprintf("--%s=json", flags.FlagOutput)} + +func (ets *E2ETestSuite) TestGetCmdList() { + val := ets.network.Validators[0] + sr := ets.Require() + + testCases := []struct { + msg string + createAuction bool + }{ + { + "list auctions when no auctions exist", + false, + }, + { + "list auctions after creating an auction", + true, + }, + } + + for _, test := range testCases { + ets.Run(fmt.Sprintf("Case %s", test.msg), func() { + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdList(), queryJSONFlag) + sr.NoError(err) + var auctions types.QueryAuctionsResponse + err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &auctions) + sr.NoError(err) + if test.createAuction { + sr.NotZero(len(auctions.Auctions.Auctions)) + } + }) + } +} diff --git a/tests/e2e/auction/suite.go b/tests/e2e/auction/suite.go index ef929af5..844c323d 100644 --- a/tests/e2e/auction/suite.go +++ b/tests/e2e/auction/suite.go @@ -13,6 +13,9 @@ import ( clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" + + types "git.vdb.to/cerc-io/laconic2d/x/auction" + "git.vdb.to/cerc-io/laconic2d/x/auction/client/cli" ) var ( @@ -27,33 +30,40 @@ type E2ETestSuite struct { cfg network.Config network *network.Network + + defaultAuctionId string } func NewE2ETestSuite(cfg network.Config) *E2ETestSuite { return &E2ETestSuite{cfg: cfg} } -func (s *E2ETestSuite) SetupSuite() { //nolint: all - s.T().Log("setting up e2e test suite") +func (ets *E2ETestSuite) SetupSuite() { //nolint: all + ets.T().Log("setting up e2e test suite") var err error - s.network, err = network.New(s.T(), s.T().TempDir(), s.cfg) - s.Require().NoError(err) + ets.network, err = network.New(ets.T(), ets.T().TempDir(), ets.cfg) + ets.Require().NoError(err) - _, err = s.network.WaitForHeight(1) - s.Require().NoError(err) + _, err = ets.network.WaitForHeight(1) + ets.Require().NoError(err) // setting up random owner and bidder accounts - s.createAccountWithBalance(ownerAccount, &ownerAddress) - s.createAccountWithBalance(bidderAccount, &bidderAddress) + ets.createAccountWithBalance(ownerAccount, &ownerAddress) + ets.createAccountWithBalance(bidderAccount, &bidderAddress) - // s.defaultAuctionID = s.createAuctionAndBid(true, false) + ets.defaultAuctionId = ets.createAuctionAndBid(true, false) } -func (s *E2ETestSuite) createAccountWithBalance(accountName string, accountAddress *string) { - val := s.network.Validators[0] - sr := s.Require() +func (ets *E2ETestSuite) TearDownSuite() { + ets.T().Log("tearing down integration test suite") + ets.network.Cleanup() +} + +func (ets *E2ETestSuite) createAccountWithBalance(accountName string, accountAddress *string) { + val := ets.network.Validators[0] + sr := ets.Require() info, _, err := val.ClientCtx.Keyring.NewMnemonic(accountName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) sr.NoError(err) @@ -63,14 +73,53 @@ func (s *E2ETestSuite) createAccountWithBalance(accountName string, accountAddre val.ClientCtx, val.Address, newAddr, - sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(200000))), + sdk.NewCoins(sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(200000))), addresscodec.NewBech32Codec("laconic"), fmt.Sprintf("--%s=%s", flags.FlagFrom, accountName), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), fmt.Sprintf("--%s=json", flags.FlagOutput), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, math.NewInt(10))).String()), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), // TODO + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(ets.cfg.BondDenom, math.NewInt(10))).String()), ) sr.NoError(err) *accountAddress = newAddr.String() } + +func (ets *E2ETestSuite) createAuctionAndBid(createAuction, createBid bool) string { + val := ets.network.Validators[0] + sr := ets.Require() + auctionId := "" + + err := ets.network.WaitForNextBlock() + sr.NoError(err) + + if createAuction { + auctionArgs := []string{ + sampleCommitTime, sampleRevealTime, + fmt.Sprintf("10%s", ets.cfg.BondDenom), + fmt.Sprintf("10%s", ets.cfg.BondDenom), + fmt.Sprintf("100%s", ets.cfg.BondDenom), + } + + resp, err := ets.executeTx(cli.GetCmdCreateAuction(), auctionArgs, ownerAccount) + sr.NoError(err) + sr.Zero(resp.Code) + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.GetCmdList(), queryJSONFlag) + sr.NoError(err) + var queryResponse types.QueryAuctionsResponse + err = val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &queryResponse) + sr.NoError(err) + auctionId = queryResponse.Auctions.Auctions[0].Id + } else { + auctionId = ets.defaultAuctionId + } + + if createBid { + bidArgs := []string{auctionId, fmt.Sprintf("200%s", ets.cfg.BondDenom)} + resp, err := ets.executeTx(cli.GetCmdCommitBid(), bidArgs, bidderAccount) + sr.NoError(err) + sr.Zero(resp.Code) + } + + return auctionId +} diff --git a/x/auction/client/cli/query.go b/x/auction/client/cli/query.go new file mode 100644 index 00000000..6cfa10a4 --- /dev/null +++ b/x/auction/client/cli/query.go @@ -0,0 +1,35 @@ +package cli + +import ( + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/spf13/cobra" + + types "git.vdb.to/cerc-io/laconic2d/x/auction" +) + +// GetCmdList queries all auctions. +func GetCmdList() *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List auctions.", + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.Auctions(cmd.Context(), &types.QueryAuctionsRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} diff --git a/x/auction/client/cli/tx.go b/x/auction/client/cli/tx.go index 90e98030..4c75a403 100644 --- a/x/auction/client/cli/tx.go +++ b/x/auction/client/cli/tx.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "fmt" "os" + "time" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" @@ -128,3 +129,60 @@ func GetCmdRevealBid() *cobra.Command { return cmd } + +func GetCmdCreateAuction() *cobra.Command { + cmd := &cobra.Command{ + Use: "create [commits-duration] [reveals-duration] [commit-fee] [reveal-fee] [minimum-bid]", + Short: "Create auction.", + Args: cobra.ExactArgs(5), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + commitsDuration, err := time.ParseDuration(args[0]) + if err != nil { + return err + } + + revealsDuration, err := time.ParseDuration(args[1]) + if err != nil { + return err + } + + commitFee, err := sdk.ParseCoinNormalized(args[2]) + if err != nil { + return err + } + + revealFee, err := sdk.ParseCoinNormalized(args[3]) + if err != nil { + return err + } + + minimumBid, err := sdk.ParseCoinNormalized(args[4]) + if err != nil { + return err + } + + params := auctiontypes.Params{ + CommitsDuration: commitsDuration, + RevealsDuration: revealsDuration, + CommitFee: commitFee, + RevealFee: revealFee, + MinimumBid: minimumBid, + } + msg := auctiontypes.NewMsgCreateAuction(params, clientCtx.GetFromAddress()) + err = msg.ValidateBasic() + if err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), &msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + return cmd +} diff --git a/x/auction/msgs.go b/x/auction/msgs.go index 6aa4f798..a21427fc 100644 --- a/x/auction/msgs.go +++ b/x/auction/msgs.go @@ -33,6 +33,27 @@ func NewMsgCommitBid(auctionId string, commitHash string, signer sdk.AccAddress) } } +// ValidateBasic Implements Msg. +func (msg MsgCreateAuction) ValidateBasic() error { + if msg.Signer == "" { + return errorsmod.Wrap(sdkerrors.ErrInvalidAddress, msg.Signer) + } + + if msg.CommitsDuration <= 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "commit phase duration invalid.") + } + + if msg.RevealsDuration <= 0 { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "reveal phase duration invalid.") + } + + if !msg.MinimumBid.IsPositive() { + return errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "minimum bid should be greater than zero.") + } + + return nil +} + // ValidateBasic Implements Msg. func (msg MsgCommitBid) ValidateBasic() error { if msg.Signer == "" {