diff --git a/cmd/network_chain_join.go b/cmd/network_chain_join.go index a6c75b7..cd8f93b 100644 --- a/cmd/network_chain_join.go +++ b/cmd/network_chain_join.go @@ -187,8 +187,25 @@ func networkChainJoinHandler(cmd *cobra.Command, args []string) error { } } - // create the message to add the validator. - return n.Join(cmd.Context(), c, launchID, gentxPath, joinOptions...) + // create requests to join as a validator + joinRequests, err := n.GetJoinRequestContents(cmd.Context(), c, launchID, gentxPath, joinOptions...) + if err != nil { + return err + } + + // simulate the join requests + if err := verifyRequestsFromRequestContents( + cmd.Context(), + cacheStorage, + nb, + launchID, + joinRequests..., + ); err != nil { + return err + } + + // send join requests + return n.SendRequests(cmd.Context(), launchID, joinRequests) } // askPublicAddress prepare questions to interactively ask for a publicAddress diff --git a/cmd/network_chain_publish.go b/cmd/network_chain_publish.go index 0961890..47283b3 100644 --- a/cmd/network_chain_publish.go +++ b/cmd/network_chain_publish.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/tendermint/spn/pkg/chainid" + launchtypes "github.com/tendermint/spn/x/launch/types" "github.com/ignite/cli-plugin-network/network" "github.com/ignite/cli-plugin-network/network/networkchain" @@ -323,7 +324,30 @@ func networkChainPublishHandler(cmd *cobra.Command, args []string) error { } if !amountCoins.IsZero() { - if err := n.SendAccountRequestForCoordinator(cmd.Context(), launchID, amountCoins); err != nil { + // create a request to add an account to the genesis + addr, err := n.AccountAddress() + if err != nil { + return err + } + addAccountRequest := launchtypes.NewGenesisAccount( + launchID, + addr, + amountCoins, + ) + + // simulate the add account request + if err := verifyRequestsFromRequestContents( + cmd.Context(), + cacheStorage, + nb, + launchID, + addAccountRequest, + ); err != nil { + return err + } + + // send the request + if err := n.SendRequest(cmd.Context(), launchID, addAccountRequest); err != nil { return err } } diff --git a/cmd/network_request_add_account.go b/cmd/network_request_add_account.go index ec46e32..740368e 100644 --- a/cmd/network_request_add_account.go +++ b/cmd/network_request_add_account.go @@ -8,6 +8,7 @@ import ( "github.com/ignite/cli/ignite/pkg/cliui" "github.com/ignite/cli/ignite/pkg/cosmosutil" "github.com/spf13/cobra" + launchtypes "github.com/tendermint/spn/x/launch/types" "github.com/ignite/cli-plugin-network/network" "github.com/ignite/cli-plugin-network/network/networkchain" @@ -47,6 +48,11 @@ func networkRequestAddAccountHandler(cmd *cobra.Command, args []string) error { session := cliui.New(cliui.StartSpinner()) defer session.End() + cacheStorage, err := newCache(cmd) + if err != nil { + return err + } + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err @@ -99,10 +105,24 @@ func networkRequestAddAccountHandler(cmd *cobra.Command, args []string) error { } } - return n.SendAccountRequest( - cmd.Context(), + // create the add account request + addAccountRequest := launchtypes.NewGenesisAccount( launchID, address, balance, ) + + // simulate the add account request + if err := verifyRequestsFromRequestContents( + cmd.Context(), + cacheStorage, + nb, + launchID, + addAccountRequest, + ); err != nil { + return err + } + + // send the request + return n.SendRequest(cmd.Context(), launchID, addAccountRequest) } diff --git a/cmd/network_request_approve.go b/cmd/network_request_approve.go index ef752b4..2a5ce02 100644 --- a/cmd/network_request_approve.go +++ b/cmd/network_request_approve.go @@ -91,7 +91,7 @@ func networkRequestApproveHandler(cmd *cobra.Command, args []string) error { // if requests must be verified, we simulate the chain in a temporary directory with the requests if !noVerification { - if err := verifyRequest(cmd.Context(), cacheStorage, nb, launchID, ids...); err != nil { + if err := verifyRequests(cmd.Context(), cacheStorage, nb, launchID, ids...); err != nil { return errors.Wrap(err, "request(s) not valid") } session.Printf("%s Request(s) %s verified\n", icons.OK, numbers.List(ids, "#")) @@ -102,7 +102,7 @@ func networkRequestApproveHandler(cmd *cobra.Command, args []string) error { for _, id := range ids { reviewals = append(reviewals, network.ApproveRequest(id)) } - if err := n.SubmitRequest(cmd.Context(), launchID, reviewals...); err != nil { + if err := n.SubmitRequestReviewals(cmd.Context(), launchID, reviewals...); err != nil { return err } diff --git a/cmd/network_request_change_param.go b/cmd/network_request_change_param.go index abe353f..0228883 100644 --- a/cmd/network_request_change_param.go +++ b/cmd/network_request_change_param.go @@ -3,6 +3,7 @@ package cmd import ( "github.com/ignite/cli/ignite/pkg/cliui" "github.com/spf13/cobra" + launchtypes "github.com/tendermint/spn/x/launch/types" "github.com/ignite/cli-plugin-network/network" "github.com/ignite/cli-plugin-network/network/networkchain" @@ -29,6 +30,11 @@ func networkRequestChangeParamHandler(cmd *cobra.Command, args []string) error { session := cliui.New(cliui.StartSpinner()) defer session.End() + cacheStorage, err := newCache(cmd) + if err != nil { + return err + } + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err @@ -71,11 +77,25 @@ func networkRequestChangeParamHandler(cmd *cobra.Command, args []string) error { return err } - return n.SendParamChangeRequest( - cmd.Context(), + // create the param change request + paramChangeRequest := launchtypes.NewParamChange( launchID, module, param, value, ) + + // simulate the param change request + if err := verifyRequestsFromRequestContents( + cmd.Context(), + cacheStorage, + nb, + launchID, + paramChangeRequest, + ); err != nil { + return err + } + + // send the request + return n.SendRequest(cmd.Context(), launchID, paramChangeRequest) } diff --git a/cmd/network_request_reject.go b/cmd/network_request_reject.go index c8c06a2..575e4bd 100644 --- a/cmd/network_request_reject.go +++ b/cmd/network_request_reject.go @@ -63,7 +63,7 @@ func networkRequestRejectHandler(cmd *cobra.Command, args []string) error { for _, id := range ids { reviewals = append(reviewals, network.RejectRequest(id)) } - if err := n.SubmitRequest(cmd.Context(), launchID, reviewals...); err != nil { + if err := n.SubmitRequestReviewals(cmd.Context(), launchID, reviewals...); err != nil { return err } diff --git a/cmd/network_request_remove_account.go b/cmd/network_request_remove_account.go index 8305107..6c34c3d 100644 --- a/cmd/network_request_remove_account.go +++ b/cmd/network_request_remove_account.go @@ -4,6 +4,7 @@ import ( "github.com/ignite/cli/ignite/pkg/cliui" "github.com/ignite/cli/ignite/pkg/cosmosutil" "github.com/spf13/cobra" + launchtypes "github.com/tendermint/spn/x/launch/types" "github.com/ignite/cli-plugin-network/network" "github.com/ignite/cli-plugin-network/network/networktypes" @@ -30,6 +31,11 @@ func networkRequestRemoveAccountHandler(cmd *cobra.Command, args []string) error session := cliui.New(cliui.StartSpinner()) defer session.End() + cacheStorage, err := newCache(cmd) + if err != nil { + return err + } + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err @@ -52,9 +58,22 @@ func networkRequestRemoveAccountHandler(cmd *cobra.Command, args []string) error return err } - return n.SendAccountRemoveRequest( - cmd.Context(), - launchID, + // create the remove account request + removeAccountRequest := launchtypes.NewAccountRemoval( address, ) + + // simulate the remove account request + if err := verifyRequestsFromRequestContents( + cmd.Context(), + cacheStorage, + nb, + launchID, + removeAccountRequest, + ); err != nil { + return err + } + + // send the request + return n.SendRequest(cmd.Context(), launchID, removeAccountRequest) } diff --git a/cmd/network_request_remove_validator.go b/cmd/network_request_remove_validator.go index b540c9a..0eaa7d1 100644 --- a/cmd/network_request_remove_validator.go +++ b/cmd/network_request_remove_validator.go @@ -4,6 +4,7 @@ import ( "github.com/ignite/cli/ignite/pkg/cliui" "github.com/ignite/cli/ignite/pkg/cosmosutil" "github.com/spf13/cobra" + launchtypes "github.com/tendermint/spn/x/launch/types" "github.com/ignite/cli-plugin-network/network" "github.com/ignite/cli-plugin-network/network/networktypes" @@ -30,6 +31,11 @@ func networkRequestRemoveValidatorHandler(cmd *cobra.Command, args []string) err session := cliui.New(cliui.StartSpinner()) defer session.End() + cacheStorage, err := newCache(cmd) + if err != nil { + return err + } + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err @@ -52,9 +58,22 @@ func networkRequestRemoveValidatorHandler(cmd *cobra.Command, args []string) err return err } - return n.SendValidatorRemoveRequest( - cmd.Context(), - launchID, + // create the remove validator request + removeValidatorRequest := launchtypes.NewValidatorRemoval( address, ) + + // simulate the remove validator request + if err := verifyRequestsFromRequestContents( + cmd.Context(), + cacheStorage, + nb, + launchID, + removeValidatorRequest, + ); err != nil { + return err + } + + // send the request + return n.SendRequest(cmd.Context(), launchID, removeValidatorRequest) } diff --git a/cmd/network_request_verify.go b/cmd/network_request_verify.go index ef7397b..b957cdd 100644 --- a/cmd/network_request_verify.go +++ b/cmd/network_request_verify.go @@ -10,9 +10,11 @@ import ( "github.com/ignite/cli/ignite/pkg/cliui/icons" "github.com/ignite/cli/ignite/pkg/numbers" "github.com/spf13/cobra" + launchtypes "github.com/tendermint/spn/x/launch/types" "github.com/ignite/cli-plugin-network/network" "github.com/ignite/cli-plugin-network/network/networkchain" + "github.com/ignite/cli-plugin-network/network/networktypes" ) // NewNetworkRequestVerify verify the request and simulate the chain. @@ -64,8 +66,7 @@ func networkRequestVerifyHandler(cmd *cobra.Command, args []string) error { } // verify the requests - - if err := verifyRequest(cmd.Context(), cacheStorage, nb, launchID, ids...); err != nil { + if err := verifyRequests(cmd.Context(), cacheStorage, nb, launchID, ids...); err != nil { session.Printf("%s Request(s) %s not valid\n", icons.NotOK, numbers.List(ids, "#")) return err } @@ -73,56 +74,103 @@ func networkRequestVerifyHandler(cmd *cobra.Command, args []string) error { return session.Printf("%s Request(s) %s verified\n", icons.OK, numbers.List(ids, "#")) } -// verifyRequest initialize the chain from the launch ID in a temporary directory -// and simulate the launch of the chain from genesis with the request IDs. -func verifyRequest( +// verifyRequests initializes the chain from the launch ID in a temporary directory +// and simulate the launch of the chain from genesis with the request IDs +func verifyRequests( ctx context.Context, cacheStorage cache.Storage, nb NetworkBuilder, launchID uint64, requestIDs ...uint64, ) error { - n, err := nb.Network() + // initialize the chain for simulation + c, n, genesisInformation, cleanup, err := initializeSimulationEnvironment(ctx, nb, launchID) if err != nil { return err } + defer cleanup() - // initialize the chain with a temporary dir - chainLaunch, err := n.ChainLaunch(ctx, launchID) + // fetch the requests from the network + requests, err := n.RequestFromIDs(ctx, launchID, requestIDs...) if err != nil { return err } - homeDir, err := os.MkdirTemp("", "") + return c.SimulateRequests( + ctx, + cacheStorage, + genesisInformation, + requests, + ) +} + +// verifyRequestsFromRequestContents initializes the chain from the launch ID in a temporary directory +// and simulate the launch of the chain from genesis with the request contents +func verifyRequestsFromRequestContents( + ctx context.Context, + cacheStorage cache.Storage, + nb NetworkBuilder, + launchID uint64, + requestContents ...launchtypes.RequestContent, +) error { + // initialize the chain for simulation + c, _, genesisInformation, cleanup, err := initializeSimulationEnvironment(ctx, nb, launchID) if err != nil { return err } - defer os.RemoveAll(homeDir) + defer cleanup() - c, err := nb.Chain( - networkchain.SourceLaunch(chainLaunch), - networkchain.WithHome(homeDir), - networkchain.WithKeyringBackend(chaincmd.KeyringBackendTest), + return c.SimulateRequests( + ctx, + cacheStorage, + genesisInformation, + networktypes.RequestsFromRequestContents(launchID, requestContents), ) +} + +// initializeSimulationEnvironment initializes the chain from the launch ID in a temporary directory for simulating requests +func initializeSimulationEnvironment( + ctx context.Context, + nb NetworkBuilder, + launchID uint64, +) ( + c *networkchain.Chain, + n network.Network, + gi networktypes.GenesisInformation, + cleanup func(), + err error, +) { + n, err = nb.Network() if err != nil { - return err + return c, n, gi, cleanup, err } // fetch the current genesis information and the requests for the chain for simulation - genesisInformation, err := n.GenesisInformation(ctx, launchID) + gi, err = n.GenesisInformation(ctx, launchID) if err != nil { - return err + return c, n, gi, cleanup, err } - requests, err := n.RequestFromIDs(ctx, launchID, requestIDs...) + // initialize the chain with a temporary dir + chainLaunch, err := n.ChainLaunch(ctx, launchID) if err != nil { - return err + return c, n, gi, cleanup, err } - return c.SimulateRequests( - ctx, - cacheStorage, - genesisInformation, - requests, + homeDir, err := os.MkdirTemp("", "") + if err != nil { + return c, n, gi, cleanup, err + } + + c, err = nb.Chain( + networkchain.SourceLaunch(chainLaunch), + networkchain.WithHome(homeDir), + networkchain.WithKeyringBackend(chaincmd.KeyringBackendTest), ) + if err != nil { + os.RemoveAll(homeDir) + return c, n, gi, cleanup, err + } + + return c, n, gi, func() { os.RemoveAll(homeDir) }, nil } diff --git a/go.mod b/go.mod index d98999e..fa13ec6 100644 --- a/go.mod +++ b/go.mod @@ -203,6 +203,7 @@ require ( github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/iancoleman/strcase v0.2.0 // indirect + github.com/ignite/modules v0.0.0-20220912090139-7c325cae763a // indirect github.com/ignite/web v0.4.3 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect @@ -326,6 +327,7 @@ require ( github.com/tdakkota/asciicheck v0.1.1 // indirect github.com/tendermint/btcd v0.1.1 // indirect github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect + github.com/tendermint/fundraising v0.3.1 // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/tendermint/tm-db v0.6.7 // indirect github.com/tetafro/godot v1.4.11 // indirect diff --git a/go.sum b/go.sum index bf9ef8f..ecd775f 100644 --- a/go.sum +++ b/go.sum @@ -886,6 +886,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1: github.com/ignite/cli v0.25.3-0.20230104180229-a712f7007658 h1:dc7tWGuW8b6iX+Ph+2pS9YUijqy4wvebldjKAOBLAyw= github.com/ignite/cli v0.25.3-0.20230104180229-a712f7007658/go.mod h1:8awEYK31HLR8ecLuVABvOX9VJChyz5D/yWWc2Pu5C2s= github.com/ignite/modules v0.0.0-20220912090139-7c325cae763a h1:0P8qg4YS0hb8jomZedhbooEKE3JZhRNAewV8+8otr6k= +github.com/ignite/modules v0.0.0-20220912090139-7c325cae763a/go.mod h1:BmcHZ5Q+9jrnL2k7U7sVOPh0FD7cshCJDxysAb8SCS0= github.com/ignite/web v0.4.3 h1:LHucUEXttzCf5JmxO5/xLKVx1Qz1o124HqF4Nii5uWQ= github.com/ignite/web v0.4.3/go.mod h1:WZWBaBYF8RazN7dE462BLpvXDY8ScacxcJ07BKwX/jY= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -1466,6 +1467,7 @@ github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrn github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= github.com/tendermint/fundraising v0.3.1 h1:S4uOV/T7YNBqXhsCZnq/TUoHB0d2kM+6tKeTD4WhLN0= +github.com/tendermint/fundraising v0.3.1/go.mod h1:7rCHXGOoFiUBD7sAZ4u+/EFq4MgQEn7tFopX6Qe6zpc= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tendermint/spn v0.2.1-0.20221125172725-052fbf576cb2 h1:3sf/j+p+XFSenqu1DNcjvW01dSPpvx06Xef3EiSvqhg= diff --git a/network/join.go b/network/join.go index be24d4c..ad900d1 100644 --- a/network/join.go +++ b/network/join.go @@ -33,14 +33,14 @@ func WithPublicAddress(addr string) JoinOption { } } -// Join to the network. -func (n Network) Join( +// GetJoinRequestContents returns the request contents to join a chain as a validator +func (n Network) GetJoinRequestContents( ctx context.Context, c Chain, launchID uint64, gentxPath string, options ...JoinOption, -) error { +) (reqs []launchtypes.RequestContent, err error) { o := joinOptions{} for _, apply := range options { apply(&o) @@ -49,19 +49,18 @@ func (n Network) Join( var ( nodeID string peer launchtypes.Peer - err error ) // parse the gentx content gentxInfo, gentx, err := cosmosutil.GentxFromPath(gentxPath) if err != nil { - return err + return reqs, err } // get the peer address if o.publicAddress != "" { if nodeID, err = c.NodeID(ctx); err != nil { - return err + return reqs, err } if xurl.IsHTTP(o.publicAddress) { @@ -72,30 +71,32 @@ func (n Network) Join( } else { // if the peer address is not specified, we parse it from the gentx memo if peer, err = ParsePeerAddress(gentxInfo.Memo); err != nil { - return err + return reqs, err } } // change the chain address prefix to spn accountAddress, err := cosmosutil.ChangeAddressPrefix(gentxInfo.DelegatorAddress, networktypes.SPN) if err != nil { - return err + return reqs, err } if !o.accountAmount.IsZero() { - if err := n.SendAccountRequest(ctx, launchID, accountAddress, o.accountAmount); err != nil { - return err - } + reqs = append(reqs, launchtypes.NewGenesisAccount( + launchID, + accountAddress, + o.accountAmount, + )) } - return n.SendValidatorRequest(ctx, launchID, peer, accountAddress, gentx, gentxInfo) -} - -func (n Network) SendAccountRequestForCoordinator(ctx context.Context, launchID uint64, amount sdk.Coins) error { - addr, err := n.account.Address(networktypes.SPN) - if err != nil { - return err - } + reqs = append(reqs, launchtypes.NewGenesisValidator( + launchID, + accountAddress, + gentx, + gentxInfo.PubKey, + gentxInfo.SelfDelegation, + peer, + )) - return n.SendAccountRequest(ctx, launchID, addr, amount) + return reqs, nil } diff --git a/network/join_test.go b/network/join_test.go index 6d67186..fe38814 100644 --- a/network/join_test.go +++ b/network/join_test.go @@ -24,7 +24,7 @@ const ( ) func TestJoin(t *testing.T) { - t.Run("successfully send join request", func(t *testing.T) { + t.Run("successfully get join request with custom public address", func(t *testing.T) { account := testutil.NewTestAccount(t, testutil.TestAccountName) tmp := t.TempDir() addr, err := account.Address(networktypes.SPN) @@ -39,96 +39,35 @@ func TestJoin(t *testing.T) { gentxPath := gentx.SaveTo(t, tmp) suite, network := newSuite(account) - suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() - suite.CosmosClientMock. - On( - "BroadcastTx", - context.Background(), - account, - launchtypes.NewMsgSendRequest( - addr, - testutil.LaunchID, - launchtypes.NewGenesisValidator( - testutil.LaunchID, - addr, - gentx.JSON(t), - []byte{}, - sdk.NewCoin(TestDenom, sdkmath.NewInt(TestAmountInt)), - launchtypes.Peer{ - Id: testutil.NodeID, - Connection: &launchtypes.Peer_TcpAddress{ - TcpAddress: testutil.TCPAddress, - }, - }), - ), - ). - Return(testutil.NewResponse(&launchtypes.MsgSendRequestResponse{ - RequestID: TestGenesisValidatorRequestID, - AutoApproved: false, - }), nil). - Once() + expectedReqs := []launchtypes.RequestContent{ + launchtypes.NewGenesisValidator( + testutil.LaunchID, + addr, + gentx.JSON(t), + []byte{}, + sdk.NewCoin(TestDenom, sdkmath.NewInt(TestAmountInt)), + launchtypes.Peer{ + Id: testutil.NodeID, + Connection: &launchtypes.Peer_TcpAddress{ + TcpAddress: testutil.TCPAddress, + }, + }, + ), + } - joinErr := network.Join( + suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() + reqs, err := network.GetJoinRequestContents( context.Background(), suite.ChainMock, testutil.LaunchID, gentxPath, WithPublicAddress(testutil.TCPAddress), ) - require.NoError(t, joinErr) - suite.AssertAllMocks(t) - }) - - t.Run("successfully send join request with custom gentx", func(t *testing.T) { - account := testutil.NewTestAccount(t, testutil.TestAccountName) - tmp := t.TempDir() - addr, err := account.Address(networktypes.SPN) require.NoError(t, err) - gentx := testutil.NewGentx( - addr, - TestDenom, - TestAmountString, - "", - testutil.PeerAddress, - ) - gentxPath := gentx.SaveTo(t, tmp) - suite, network := newSuite(account) - - suite.CosmosClientMock. - On( - "BroadcastTx", - context.Background(), - account, - launchtypes.NewMsgSendRequest( - addr, - testutil.LaunchID, - launchtypes.NewGenesisValidator( - testutil.LaunchID, - addr, - gentx.JSON(t), - []byte{}, - sdk.NewCoin(TestDenom, sdkmath.NewInt(TestAmountInt)), - launchtypes.Peer{ - Id: testutil.NodeID, - Connection: &launchtypes.Peer_TcpAddress{ - TcpAddress: testutil.TCPAddress, - }, - }, - ), - ), - ). - Return(testutil.NewResponse(&launchtypes.MsgSendRequestResponse{ - RequestID: TestGenesisValidatorRequestID, - AutoApproved: false, - }), nil). - Once() - - joinErr := network.Join(context.Background(), suite.ChainMock, testutil.LaunchID, gentxPath) - require.NoError(t, joinErr) - suite.AssertAllMocks(t) + require.ElementsMatch(t, expectedReqs, reqs) }) - t.Run("failed to send join request, failed to broadcast join tx", func(t *testing.T) { + t.Run("successfully get join request with public address read from the gentx", func(t *testing.T) { account := testutil.NewTestAccount(t, testutil.TestAccountName) tmp := t.TempDir() addr, err := account.Address(networktypes.SPN) @@ -142,51 +81,34 @@ func TestJoin(t *testing.T) { ) gentxPath := gentx.SaveTo(t, tmp) suite, network := newSuite(account) - expectedError := errors.New("failed to add validator") - suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() - suite.CosmosClientMock. - On( - "BroadcastTx", - context.Background(), - account, - launchtypes.NewMsgSendRequest( - addr, - testutil.LaunchID, - launchtypes.NewGenesisValidator( - testutil.LaunchID, - addr, - gentx.JSON(t), - []byte{}, - sdk.NewCoin(TestDenom, sdkmath.NewInt(TestAmountInt)), - launchtypes.Peer{ - Id: testutil.NodeID, - Connection: &launchtypes.Peer_TcpAddress{ - TcpAddress: testutil.TCPAddress, - }, - }, - ), - ), - ). - Return( - testutil.NewResponse(&launchtypes.MsgSendRequestResponse{}), - expectedError, - ). - Once() - - joinErr := network.Join( + expectedReqs := []launchtypes.RequestContent{ + launchtypes.NewGenesisValidator( + testutil.LaunchID, + addr, + gentx.JSON(t), + []byte{}, + sdk.NewCoin(TestDenom, sdkmath.NewInt(TestAmountInt)), + launchtypes.Peer{ + Id: testutil.NodeID, + Connection: &launchtypes.Peer_TcpAddress{ + TcpAddress: testutil.TCPAddress, + }, + }, + ), + } + + reqs, err := network.GetJoinRequestContents( context.Background(), suite.ChainMock, testutil.LaunchID, gentxPath, - WithPublicAddress(testutil.TCPAddress), ) - require.Error(t, joinErr) - require.Equal(t, expectedError, joinErr) - suite.AssertAllMocks(t) + require.NoError(t, err) + require.ElementsMatch(t, expectedReqs, reqs) }) - t.Run("successfully send join request with account request", func(t *testing.T) { + t.Run("successfully get join request with account request", func(t *testing.T) { account := testutil.NewTestAccount(t, testutil.TestAccountName) tmp := t.TempDir() addr, err := account.Address(networktypes.SPN) @@ -201,57 +123,29 @@ func TestJoin(t *testing.T) { gentxPath := gentx.SaveTo(t, tmp) suite, network := newSuite(account) - suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() - suite.CosmosClientMock. - On( - "BroadcastTx", - context.Background(), - account, - launchtypes.NewMsgSendRequest( - addr, - testutil.LaunchID, - launchtypes.NewGenesisValidator( - testutil.LaunchID, - addr, - gentx.JSON(t), - []byte{}, - sdk.NewCoin(TestDenom, sdkmath.NewInt(TestAmountInt)), - launchtypes.Peer{ - Id: testutil.NodeID, - Connection: &launchtypes.Peer_TcpAddress{ - TcpAddress: testutil.TCPAddress, - }, - }, - ), - ), - ). - Return(testutil.NewResponse(&launchtypes.MsgSendRequestResponse{ - RequestID: TestGenesisValidatorRequestID, - AutoApproved: false, - }), nil). - Once() - suite.CosmosClientMock. - On( - "BroadcastTx", - context.Background(), - account, - launchtypes.NewMsgSendRequest( - addr, - testutil.LaunchID, - launchtypes.NewGenesisAccount( - testutil.LaunchID, - addr, - sdk.NewCoins(sdk.NewCoin(TestDenom, sdkmath.NewInt(TestAmountInt))), - ), - ), - ). - Return(testutil.NewResponse(&launchtypes.MsgSendRequestResponse{ - RequestID: TestAccountRequestID, - AutoApproved: false, - }), nil). - Once() + expectedReqs := []launchtypes.RequestContent{ + launchtypes.NewGenesisValidator( + testutil.LaunchID, + addr, + gentx.JSON(t), + []byte{}, + sdk.NewCoin(TestDenom, sdkmath.NewInt(TestAmountInt)), + launchtypes.Peer{ + Id: testutil.NodeID, + Connection: &launchtypes.Peer_TcpAddress{ + TcpAddress: testutil.TCPAddress, + }, + }, + ), + launchtypes.NewGenesisAccount( + testutil.LaunchID, + addr, + sdk.NewCoins(sdk.NewCoin(TestDenom, sdkmath.NewInt(TestAmountInt))), + ), + } - joinErr := network.Join( + suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() + reqs, err := network.GetJoinRequestContents( context.Background(), suite.ChainMock, testutil.LaunchID, @@ -259,11 +153,11 @@ func TestJoin(t *testing.T) { WithAccountRequest(sdk.NewCoins(sdk.NewCoin(TestDenom, sdkmath.NewInt(TestAmountInt)))), WithPublicAddress(testutil.TCPAddress), ) - require.NoError(t, joinErr) - suite.AssertAllMocks(t) + require.NoError(t, err) + require.ElementsMatch(t, expectedReqs, reqs) }) - t.Run("failed to send join request, failed to read node id", func(t *testing.T) { + t.Run("failed to get join request, failed to read node id", func(t *testing.T) { account := testutil.NewTestAccount(t, testutil.TestAccountName) tmp := t.TempDir() addr, err := account.Address(networktypes.SPN) @@ -284,29 +178,26 @@ func TestJoin(t *testing.T) { Return("", expectedError). Once() - joinErr := network.Join( + _, err = network.GetJoinRequestContents( context.Background(), suite.ChainMock, testutil.LaunchID, gentxPath, WithPublicAddress(testutil.TCPAddress), ) - require.Error(t, joinErr) - require.Equal(t, expectedError, joinErr) + require.ErrorIs(t, err, expectedError) suite.AssertAllMocks(t) }) - t.Run("failed to send join request, failed to read gentx", func(t *testing.T) { + t.Run("failed to get join request, failed to read gentx", func(t *testing.T) { var ( account = testutil.NewTestAccount(t, testutil.TestAccountName) gentxPath = "invalid/path" suite, network = newSuite(account) - expectedError = errors.New("chain home folder is not initialized yet: invalid/path") ) - joinErr := network.Join(context.Background(), suite.ChainMock, testutil.LaunchID, gentxPath) - require.Error(t, joinErr) - require.Equal(t, expectedError, joinErr) + _, err := network.GetJoinRequestContents(context.Background(), suite.ChainMock, testutil.LaunchID, gentxPath) + require.Error(t, err) suite.AssertAllMocks(t) }) } diff --git a/network/network.go b/network/network.go index c74e57f..b0f6cb6 100644 --- a/network/network.go +++ b/network/network.go @@ -20,6 +20,8 @@ import ( "github.com/ignite/cli/ignite/pkg/cosmosclient" "github.com/ignite/cli/ignite/pkg/events" "github.com/ignite/cli/ignite/pkg/xtime" + + "github.com/ignite/cli-plugin-network/network/networktypes" ) //go:generate mockery --name CosmosClient --case underscore @@ -150,3 +152,8 @@ func ParseID(id string) (uint64, error) { } return objID, nil } + +// AccountAddress returns the address of the account used by the network builder +func (n Network) AccountAddress() (string, error) { + return n.account.Address(networktypes.SPN) +} diff --git a/network/networktypes/request.go b/network/networktypes/request.go index 24306cc..c1ed684 100644 --- a/network/networktypes/request.go +++ b/network/networktypes/request.go @@ -10,6 +10,25 @@ import ( "github.com/ignite/cli/ignite/pkg/xtime" ) +// Request action descriptions +const ( + RequestActionAddAccount = "add account to the network" + RequestActionAddValidator = "join the network as a validator" + RequestActionAddVestingAccount = "add vesting account to the network" + RequestActionRemoveAccount = "remove account from the network" + RequestActionRemoveValidator = "remove validator from the network" + RequestActionChangeParams = "change param on the network" + + RequestActionResultAddAccount = "account added to the network" + RequestActionResultAddValidator = "Validator added to the network" + RequestActionResultAddVestingAccount = "vesting account added to the network" + RequestActionResultRemoveAccount = "account removed from network" + RequestActionResultRemoveValidator = "validator removed from network" + RequestActionResultChangeParams = "param changed on network" + + RequestActionUnrecognized = "" +) + type ( // Request represents the launch Request of a chain on SPN. Request struct { @@ -34,6 +53,60 @@ func ToRequest(request launchtypes.Request) Request { } } +// RequestsFromRequestContents creates a list of requests from a list request contents to simulate requests that have not been sent to request pool yet +// The request ID is set to 0 for the first request and incremented for each request, other values are not set +func RequestsFromRequestContents(launchID uint64, contents []launchtypes.RequestContent) []Request { + requests := make([]Request, len(contents)) + for i, content := range contents { + requests[i] = Request{ + LaunchID: launchID, + RequestID: uint64(i), + Content: content, + } + } + return requests +} + +// RequestActionDescriptionFromContent describes the action of the request from its content +func RequestActionDescriptionFromContent(content launchtypes.RequestContent) string { + switch content.Content.(type) { + case *launchtypes.RequestContent_GenesisAccount: + return RequestActionAddAccount + case *launchtypes.RequestContent_GenesisValidator: + return RequestActionAddValidator + case *launchtypes.RequestContent_VestingAccount: + return RequestActionAddVestingAccount + case *launchtypes.RequestContent_AccountRemoval: + return RequestActionRemoveAccount + case *launchtypes.RequestContent_ValidatorRemoval: + return RequestActionRemoveValidator + case *launchtypes.RequestContent_ParamChange: + return RequestActionChangeParams + default: + return RequestActionUnrecognized + } +} + +// RequestActionResultDescriptionFromContent describe the result of the action of the request from its content +func RequestActionResultDescriptionFromContent(content launchtypes.RequestContent) string { + switch content.Content.(type) { + case *launchtypes.RequestContent_GenesisAccount: + return RequestActionResultAddAccount + case *launchtypes.RequestContent_GenesisValidator: + return RequestActionResultAddValidator + case *launchtypes.RequestContent_VestingAccount: + return RequestActionResultAddVestingAccount + case *launchtypes.RequestContent_AccountRemoval: + return RequestActionResultRemoveAccount + case *launchtypes.RequestContent_ValidatorRemoval: + return RequestActionResultRemoveValidator + case *launchtypes.RequestContent_ParamChange: + return RequestActionResultChangeParams + default: + return RequestActionUnrecognized + } +} + // VerifyRequest verifies the validity of the request from its content (static check). func VerifyRequest(request Request) error { req, ok := request.Content.Content.(*launchtypes.RequestContent_GenesisValidator) diff --git a/network/networktypes/request_test.go b/network/networktypes/request_test.go index b2fb98b..4c13f98 100644 --- a/network/networktypes/request_test.go +++ b/network/networktypes/request_test.go @@ -3,17 +3,220 @@ package networktypes_test import ( "encoding/base64" "fmt" + "math/rand" "testing" sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + spnsample "github.com/tendermint/spn/testutil/sample" launchtypes "github.com/tendermint/spn/x/launch/types" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/ignite/cli-plugin-network/network/networktypes" ) +var ( + r = rand.New(rand.NewSource(1)) + SampleRequestAddAccount = launchtypes.NewGenesisAccount(0, "spn1dd246y", spnsample.Coins(r)) + SampleRequestAddValidator = launchtypes.NewGenesisValidator( + 0, + "spn1dd246y", + spnsample.Bytes(r, 300), + spnsample.Bytes(r, 30), + spnsample.Coin(r), + spnsample.GenesisValidatorPeer(r), + ) + SampleRequestAddVestingAccount = launchtypes.NewVestingAccount(0, "spn1dd246y", spnsample.VestingOptions(r)) + SampleRequestRemoveAccount = launchtypes.NewAccountRemoval("spn1dd246y") + SampleRequestRemoveValidator = launchtypes.NewValidatorRemoval("spn1dd246y") + SampleRequestChangeParam = launchtypes.NewParamChange(0, "foo", "bar", spnsample.Bytes(r, 30)) +) + +func TestRequestsFromRequestContents(t *testing.T) { + tests := []struct { + name string + launchID uint64 + reqs []launchtypes.RequestContent + want []networktypes.Request + }{ + { + name: "empty request contents", + launchID: 0, + reqs: []launchtypes.RequestContent{}, + want: []networktypes.Request{}, + }, + { + name: "one request content", + launchID: 1, + reqs: []launchtypes.RequestContent{ + launchtypes.NewGenesisAccount( + 1, + "spn1dd246y", + sdk.NewCoins(sdk. + NewCoin("stake", sdkmath.NewInt(1000)), + ), + ), + }, + want: []networktypes.Request{ + { + LaunchID: 1, + RequestID: 0, + Content: launchtypes.NewGenesisAccount( + 1, + "spn1dd246y", + sdk.NewCoins(sdk. + NewCoin("stake", sdkmath.NewInt(1000)), + ), + ), + }, + }, + }, + { + name: "multiple request contents", + launchID: 2, + reqs: []launchtypes.RequestContent{ + launchtypes.NewGenesisAccount( + 2, + "spn5s5z2x", + sdk.NewCoins(sdk. + NewCoin("foo", sdkmath.NewInt(2000)), + ), + ), + launchtypes.NewGenesisAccount( + 2, + "spn2x2x2x", + sdk.NewCoins(sdk. + NewCoin("bar", sdkmath.NewInt(5000)), + ), + ), + }, + want: []networktypes.Request{ + { + LaunchID: 2, + RequestID: 0, + Content: launchtypes.NewGenesisAccount( + 2, + "spn5s5z2x", + sdk.NewCoins(sdk. + NewCoin("foo", sdkmath.NewInt(2000)), + ), + ), + }, + { + LaunchID: 2, + RequestID: 1, + Content: launchtypes.NewGenesisAccount( + 2, + "spn2x2x2x", + sdk.NewCoins(sdk. + NewCoin("bar", sdkmath.NewInt(5000)), + ), + ), + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := networktypes.RequestsFromRequestContents(tt.launchID, tt.reqs) + require.Equal(t, tt.want, got) + }) + } +} + +func TestRequestActionDescriptionFromContent(t *testing.T) { + tests := []struct { + name string + req launchtypes.RequestContent + want string + }{ + { + name: "add account request content should return correct description", + req: SampleRequestAddAccount, + want: networktypes.RequestActionAddAccount, + }, + { + name: "add validator request content should return correct description", + req: SampleRequestAddValidator, + want: networktypes.RequestActionAddValidator, + }, + { + name: "add vesting account request content should return correct description", + req: SampleRequestAddVestingAccount, + want: networktypes.RequestActionAddVestingAccount, + }, + { + name: "remove account request content should return correct description", + req: SampleRequestRemoveAccount, + want: networktypes.RequestActionRemoveAccount, + }, + { + name: "remove validator request content should return correct description", + req: SampleRequestRemoveValidator, + want: networktypes.RequestActionRemoveValidator, + }, + { + name: "change params request content should return correct description", + req: SampleRequestChangeParam, + want: networktypes.RequestActionChangeParams, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := networktypes.RequestActionDescriptionFromContent(tt.req) + require.Equal(t, tt.want, got) + }) + } +} + +func TestRequestActionResultDescriptionFromContent(t *testing.T) { + tests := []struct { + name string + req launchtypes.RequestContent + want string + }{ + { + name: "add account request content should return correct result description", + req: SampleRequestAddAccount, + want: networktypes.RequestActionResultAddAccount, + }, + { + name: "add validator request content should return correct result description", + req: SampleRequestAddValidator, + want: networktypes.RequestActionResultAddValidator, + }, + { + name: "add vesting account request content should return correct result description", + req: SampleRequestAddVestingAccount, + want: networktypes.RequestActionResultAddVestingAccount, + }, + { + name: "remove account request content should return correct result description", + req: SampleRequestRemoveAccount, + want: networktypes.RequestActionResultRemoveAccount, + }, + { + name: "remove validator request content should return correct result description", + req: SampleRequestRemoveValidator, + want: networktypes.RequestActionResultRemoveValidator, + }, + { + name: "change params request content should return correct result description", + req: SampleRequestChangeParam, + want: networktypes.RequestActionResultChangeParams, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := networktypes.RequestActionResultDescriptionFromContent(tt.req) + require.Equal(t, tt.want, got) + }) + } +} + func TestVerifyAddValidatorRequest(t *testing.T) { gentx := []byte(`{ "body": { diff --git a/network/request.go b/network/request.go index a36e8eb..8f66ed9 100644 --- a/network/request.go +++ b/network/request.go @@ -5,8 +5,6 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/ignite/cli/ignite/pkg/cliui/icons" - "github.com/ignite/cli/ignite/pkg/cosmosutil" "github.com/ignite/cli/ignite/pkg/events" launchtypes "github.com/tendermint/spn/x/launch/types" @@ -75,8 +73,8 @@ func (n Network) RequestFromIDs(ctx context.Context, launchID uint64, requestIDs return reqs, nil } -// SubmitRequest submits reviewals for proposals in batch for chain. -func (n Network) SubmitRequest(ctx context.Context, launchID uint64, reviewal ...Reviewal) error { +// SubmitRequestReviewals submits reviewals for proposals in batch for chain. +func (n Network) SubmitRequestReviewals(ctx context.Context, launchID uint64, reviewal ...Reviewal) error { n.ev.Send("Submitting requests...", events.ProgressStart()) addr, err := n.account.Address(networktypes.SPN) @@ -103,12 +101,11 @@ func (n Network) SubmitRequest(ctx context.Context, launchID uint64, reviewal .. return res.Decode(&requestRes) } -// SendAccountRequest creates an add AddAccount request message. -func (n Network) SendAccountRequest( +// SendRequest creates and sends the Request message to SPN. +func (n Network) SendRequest( ctx context.Context, launchID uint64, - address string, - amount sdk.Coins, + content launchtypes.RequestContent, ) error { addr, err := n.account.Address(networktypes.SPN) if err != nil { @@ -118,108 +115,7 @@ func (n Network) SendAccountRequest( msg := launchtypes.NewMsgSendRequest( addr, launchID, - launchtypes.NewGenesisAccount( - launchID, - address, - amount, - ), - ) - - n.ev.Send("Broadcasting account transactions", events.ProgressStart()) - - res, err := n.cosmos.BroadcastTx(ctx, n.account, msg) - if err != nil { - return err - } - - var requestRes launchtypes.MsgSendRequestResponse - if err := res.Decode(&requestRes); err != nil { - return err - } - - if requestRes.AutoApproved { - n.ev.Send( - "Account added to the network by the coordinator!", - events.Icon(icons.Bullet), - events.ProgressFinish(), - ) - } else { - n.ev.Send( - fmt.Sprintf("Request %d to add account to the network has been submitted!", requestRes.RequestID), - events.Icon(icons.Bullet), - events.ProgressFinish(), - ) - } - return nil -} - -// SendValidatorRequest creates the RequestAddValidator message into the SPN. -func (n Network) SendValidatorRequest( - ctx context.Context, - launchID uint64, - peer launchtypes.Peer, - valAddress string, - gentx []byte, - gentxInfo cosmosutil.GentxInfo, -) error { - addr, err := n.account.Address(networktypes.SPN) - if err != nil { - return err - } - - msg := launchtypes.NewMsgSendRequest( - addr, - launchID, - launchtypes.NewGenesisValidator( - launchID, - valAddress, - gentx, - gentxInfo.PubKey, - gentxInfo.SelfDelegation, - peer, - ), - ) - - n.ev.Send("Broadcasting validator transaction", events.ProgressStart()) - - res, err := n.cosmos.BroadcastTx(ctx, n.account, msg) - if err != nil { - return err - } - - var requestRes launchtypes.MsgSendRequestResponse - if err := res.Decode(&requestRes); err != nil { - return err - } - - if requestRes.AutoApproved { - n.ev.Send("Validator added to the network by the coordinator!", events.ProgressFinish()) - } else { - n.ev.Send( - fmt.Sprintf("Request %d to join the network as a validator has been submitted!", requestRes.RequestID), - events.ProgressFinish(), - ) - } - return nil -} - -// SendValidatorRemoveRequest creates the RequestRemoveValidator message to SPN. -func (n Network) SendValidatorRemoveRequest( - ctx context.Context, - launchID uint64, - valAddress string, -) error { - addr, err := n.account.Address(networktypes.SPN) - if err != nil { - return err - } - - msg := launchtypes.NewMsgSendRequest( - addr, - launchID, - launchtypes.NewValidatorRemoval( - valAddress, - ), + content, ) n.ev.Send("Broadcasting transaction", events.ProgressStart()) @@ -235,55 +131,16 @@ func (n Network) SendValidatorRemoveRequest( } if requestRes.AutoApproved { - n.ev.Send("Validator removed from network by the coordinator!", events.ProgressFinish()) - } else { - n.ev.Send( - fmt.Sprintf( - "Request %d to remove validator from the network has been submitted!", requestRes.RequestID, - ), - events.ProgressFinish(), - ) - } - return nil -} - -// SendAccountRemoveRequest creates the RequestRemoveAccount message to SPN. -func (n Network) SendAccountRemoveRequest( - ctx context.Context, - launchID uint64, - address string, -) error { - addr, err := n.account.Address(networktypes.SPN) - if err != nil { - return err - } - - msg := launchtypes.NewMsgSendRequest( - addr, - launchID, - launchtypes.NewAccountRemoval( - address, + n.ev.Send(fmt.Sprintf( + "%s by the coordinator!", networktypes.RequestActionResultDescriptionFromContent(content), ), - ) - - n.ev.Send("Broadcasting transaction", events.ProgressStart()) - - res, err := n.cosmos.BroadcastTx(ctx, n.account, msg) - if err != nil { - return err - } - - var requestRes launchtypes.MsgSendRequestResponse - if err := res.Decode(&requestRes); err != nil { - return err - } - - if requestRes.AutoApproved { - n.ev.Send("Account removed from network by the coordinator!", events.ProgressFinish()) + events.ProgressFinish()) } else { n.ev.Send( fmt.Sprintf( - "Request %d to remove account from the network has been submitted!", requestRes.RequestID, + "Request %d to %s has been submitted!", + requestRes.RequestID, + networktypes.RequestActionDescriptionFromContent(content), ), events.ProgressFinish(), ) @@ -291,51 +148,16 @@ func (n Network) SendAccountRemoveRequest( return nil } -// SendParamChangeRequest creates the RequestParamChange message to SPN. -func (n Network) SendParamChangeRequest( +// SendRequests creates and sends the Request message to SPN +func (n Network) SendRequests( ctx context.Context, launchID uint64, - module, - param string, - value []byte, + contents []launchtypes.RequestContent, ) error { - addr, err := n.account.Address(networktypes.SPN) - if err != nil { - return err - } - - msg := launchtypes.NewMsgSendRequest( - addr, - launchID, - launchtypes.NewParamChange( - launchID, - module, - param, - value, - ), - ) - - n.ev.Send("Broadcasting transaction", events.ProgressStart()) - - res, err := n.cosmos.BroadcastTx(ctx, n.account, msg) - if err != nil { - return err - } - - var requestRes launchtypes.MsgSendRequestResponse - if err := res.Decode(&requestRes); err != nil { - return err - } - - if requestRes.AutoApproved { - n.ev.Send("Param changed on network by the coordinator!", events.ProgressFinish()) - } else { - n.ev.Send( - fmt.Sprintf( - "Request %d to change param on the network has been submitted!", requestRes.RequestID, - ), - events.ProgressFinish(), - ) + for _, content := range contents { + if err := n.SendRequest(ctx, launchID, content); err != nil { + return err + } } return nil } diff --git a/network/request_test.go b/network/request_test.go index 021a81e..9085685 100644 --- a/network/request_test.go +++ b/network/request_test.go @@ -11,7 +11,7 @@ import ( "github.com/ignite/cli-plugin-network/network/testutil" ) -func TestRequestParamChange(t *testing.T) { +func TestSendRequest(t *testing.T) { t.Run("successfully send request", func(t *testing.T) { var ( account = testutil.NewTestAccount(t, testutil.TestAccountName) @@ -46,7 +46,12 @@ func TestRequestParamChange(t *testing.T) { }), nil). Once() - sendRequestError := network.SendParamChangeRequest(context.Background(), testutil.LaunchID, module, param, value) + sendRequestError := network.SendRequest(context.Background(), testutil.LaunchID, launchtypes.NewParamChange( + testutil.LaunchID, + module, + param, + value, + )) require.NoError(t, sendRequestError) suite.AssertAllMocks(t) })