From 2e538383e46664bf3e84081b68c0bf83c64eda86 Mon Sep 17 00:00:00 2001 From: Danilo Pantani Date: Tue, 10 May 2022 17:15:39 -0300 Subject: [PATCH 1/8] fix(network): fix validator pubkey parser from gentx (#2456) * fix validator pubkey parser from gentx * fix unit tests * fix unit tests --- ignite/pkg/cosmosgen/cosmosgen_test.go | 3 +- ignite/pkg/cosmosutil/gentx.go | 26 ++++++------ ignite/pkg/cosmosutil/gentx_test.go | 40 +++++-------------- .../services/network/networktypes/request.go | 7 ++-- .../network/networktypes/request_test.go | 20 ++++++---- 5 files changed, 40 insertions(+), 56 deletions(-) diff --git a/ignite/pkg/cosmosgen/cosmosgen_test.go b/ignite/pkg/cosmosgen/cosmosgen_test.go index 412f2e260d..7297136893 100644 --- a/ignite/pkg/cosmosgen/cosmosgen_test.go +++ b/ignite/pkg/cosmosgen/cosmosgen_test.go @@ -3,9 +3,10 @@ package cosmosgen import ( "testing" + "github.com/stretchr/testify/require" + "github.com/ignite-hq/cli/ignite/pkg/cosmosanalysis/module" "github.com/ignite-hq/cli/ignite/pkg/protoanalysis" - "github.com/stretchr/testify/require" ) func TestVuexStoreModulePath(t *testing.T) { diff --git a/ignite/pkg/cosmosutil/gentx.go b/ignite/pkg/cosmosutil/gentx.go index 1fdfdb4d2d..ad6cc56bb5 100644 --- a/ignite/pkg/cosmosutil/gentx.go +++ b/ignite/pkg/cosmosutil/gentx.go @@ -1,24 +1,24 @@ package cosmosutil import ( - "bytes" + "encoding/base64" "encoding/json" "errors" + "fmt" "os" + "github.com/tendermint/tendermint/crypto/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" ) var GentxFilename = "gentx.json" type ( - // PubKey represents the public key in bytes array - PubKey []byte - // GentxInfo represents the basic info about gentx file GentxInfo struct { DelegatorAddress string - PubKey PubKey + PubKey ed25519.PubKey SelfDelegation sdk.Coin Memo string } @@ -30,7 +30,8 @@ type ( DelegatorAddress string `json:"delegator_address"` ValidatorAddress string `json:"validator_address"` PubKey struct { - Key string `json:"key"` + Type string `json:"@type"` + Key string `json:"key"` } `json:"pubkey"` Value struct { Denom string `json:"denom"` @@ -42,12 +43,6 @@ type ( } ) -// Equal returns true if the public keys are equal -func (pb PubKey) Equal(key []byte) bool { - res := bytes.Compare(pb, key) - return res == 0 -} - // GentxFromPath returns GentxInfo from the json file func GentxFromPath(path string) (info GentxInfo, gentx []byte, err error) { if _, err := os.Stat(path); os.IsNotExist(err) { @@ -80,7 +75,12 @@ func ParseGentx(gentx []byte) (info GentxInfo, file []byte, err error) { info.Memo = stargateGentx.Body.Memo info.DelegatorAddress = stargateGentx.Body.Messages[0].DelegatorAddress - info.PubKey = []byte(stargateGentx.Body.Messages[0].PubKey.Key) + + pb := stargateGentx.Body.Messages[0].PubKey.Key + info.PubKey, err = base64.StdEncoding.DecodeString(pb) + if err != nil { + return info, gentx, fmt.Errorf("invalid validator public key %s", err.Error()) + } amount, ok := sdk.NewIntFromString(stargateGentx.Body.Messages[0].Value.Amount) if !ok { diff --git a/ignite/pkg/cosmosutil/gentx_test.go b/ignite/pkg/cosmosutil/gentx_test.go index 2e51157e77..97b09cf963 100644 --- a/ignite/pkg/cosmosutil/gentx_test.go +++ b/ignite/pkg/cosmosutil/gentx_test.go @@ -1,15 +1,22 @@ package cosmosutil_test import ( + "encoding/base64" "testing" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" ) func TestParseGentx(t *testing.T) { + pk1, err := base64.StdEncoding.DecodeString("aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs=") + require.NoError(t, err) + pk2, err := base64.StdEncoding.DecodeString("OL+EIoo7DwyaBFDbPbgAhwS5rvgIqoUa0x8qWqzfQVQ=") + require.NoError(t, err) + tests := []struct { name string gentxPath string @@ -21,7 +28,7 @@ func TestParseGentx(t *testing.T) { gentxPath: "testdata/gentx1.json", wantInfo: cosmosutil.GentxInfo{ DelegatorAddress: "cosmos1dd246yq6z5vzjz9gh8cff46pll75yyl8ygndsj", - PubKey: []byte("aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs="), + PubKey: ed25519.PubKey(pk1), SelfDelegation: sdk.Coin{ Denom: "stake", Amount: sdk.NewInt(95000000), @@ -33,7 +40,7 @@ func TestParseGentx(t *testing.T) { gentxPath: "testdata/gentx2.json", wantInfo: cosmosutil.GentxInfo{ DelegatorAddress: "cosmos1mmlqwyqk7neqegffp99q86eckpm4pjah3ytlpa", - PubKey: []byte("OL+EIoo7DwyaBFDbPbgAhwS5rvgIqoUa0x8qWqzfQVQ="), + PubKey: ed25519.PubKey(pk2), SelfDelegation: sdk.Coin{ Denom: "stake", Amount: sdk.NewInt(95000000), @@ -62,32 +69,3 @@ func TestParseGentx(t *testing.T) { }) } } - -func TestPubKey_Equal(t *testing.T) { - tests := []struct { - name string - pb []byte - cmpKey []byte - want bool - }{ - { - name: "equal public keys", - pb: []byte("aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs="), - cmpKey: []byte("aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs="), - want: true, - }, - { - name: "not equal public keys", - pb: []byte("aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs="), - cmpKey: []byte("EIoo7DwyaBFDbPbgAhwS5rvgIqoUa0x8qWqzfQVQ="), - want: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - pb := cosmosutil.PubKey(tt.pb) - got := pb.Equal(tt.cmpKey) - require.Equal(t, tt.want, got) - }) - } -} diff --git a/ignite/services/network/networktypes/request.go b/ignite/services/network/networktypes/request.go index a95d64f6ea..c7e3769bbe 100644 --- a/ignite/services/network/networktypes/request.go +++ b/ignite/services/network/networktypes/request.go @@ -4,6 +4,7 @@ import ( "fmt" launchtypes "github.com/tendermint/spn/x/launch/types" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" "github.com/ignite-hq/cli/ignite/pkg/xtime" @@ -80,11 +81,11 @@ func VerifyAddValidatorRequest(req *launchtypes.RequestContent_GenesisValidator) } // Check validator address - if !info.PubKey.Equal(consPubKey) { + if !info.PubKey.Equals(ed25519.PubKey(consPubKey)) { return fmt.Errorf( "the consensus pub key %s doesn't match the one inside the gentx %s", - string(consPubKey), - string(info.PubKey), + ed25519.PubKey(consPubKey).String(), + info.PubKey.String(), ) } diff --git a/ignite/services/network/networktypes/request_test.go b/ignite/services/network/networktypes/request_test.go index 5bfacd4817..0e0011de47 100644 --- a/ignite/services/network/networktypes/request_test.go +++ b/ignite/services/network/networktypes/request_test.go @@ -1,12 +1,14 @@ package networktypes_test import ( + "encoding/base64" "fmt" "testing" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" launchtypes "github.com/tendermint/spn/x/launch/types" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/ignite-hq/cli/ignite/services/network/networktypes" ) @@ -30,6 +32,8 @@ func TestVerifyAddValidatorRequest(t *testing.T) { ] } }`) + pk, err := base64.StdEncoding.DecodeString("aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs=") + require.NoError(t, err) tests := []struct { name string @@ -42,7 +46,7 @@ func TestVerifyAddValidatorRequest(t *testing.T) { GenesisValidator: &launchtypes.GenesisValidator{ Address: "spn1dd246yq6z5vzjz9gh8cff46pll75yyl8c5tt7g", GenTx: gentx, - ConsPubKey: []byte("aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs="), + ConsPubKey: ed25519.PubKey(pk), SelfDelegation: sdk.NewCoin("stake", sdk.NewInt(95000000)), Peer: launchtypes.NewPeerConn("nodeid", "127.163.0.1:2446"), }, @@ -54,7 +58,7 @@ func TestVerifyAddValidatorRequest(t *testing.T) { GenesisValidator: &launchtypes.GenesisValidator{ Address: "spn1dd246yq6z5vzjz9gh8cff46pll75yyl8c5tt7g", GenTx: gentx, - ConsPubKey: []byte("aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs="), + ConsPubKey: ed25519.PubKey(pk), SelfDelegation: sdk.NewCoin("stake", sdk.NewInt(95000000)), Peer: launchtypes.NewPeerConn("nodeid", "122.114.800.11"), }, @@ -67,7 +71,7 @@ func TestVerifyAddValidatorRequest(t *testing.T) { GenesisValidator: &launchtypes.GenesisValidator{ Address: "spn1dd246yq6z5vzjz9gh8cff46pll75yyl8c5tt7g", GenTx: []byte(`{}`), - ConsPubKey: []byte("aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs="), + ConsPubKey: ed25519.PubKey(pk), SelfDelegation: sdk.NewCoin("stake", sdk.NewInt(95000000)), Peer: launchtypes.NewPeerConn("nodeid", "127.163.0.1:2446"), }, @@ -80,7 +84,7 @@ func TestVerifyAddValidatorRequest(t *testing.T) { GenesisValidator: &launchtypes.GenesisValidator{ Address: "spn1dd246yq6z5vzjz9gh8cff46pll75yyl8c5tt7g", GenTx: gentx, - ConsPubKey: []byte("aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs="), + ConsPubKey: ed25519.PubKey(pk), SelfDelegation: sdk.NewCoin("foo", sdk.NewInt(95000000)), Peer: launchtypes.NewPeerConn("nodeid", "127.163.0.1:2446"), }, @@ -93,7 +97,7 @@ func TestVerifyAddValidatorRequest(t *testing.T) { GenesisValidator: &launchtypes.GenesisValidator{ Address: "spn1dd246yq6z5vzjz9gh8cff46pll75yyl8c5tt7g", GenTx: gentx, - ConsPubKey: []byte("aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs="), + ConsPubKey: ed25519.PubKey(pk), SelfDelegation: sdk.NewCoin("stake", sdk.NewInt(3)), Peer: launchtypes.NewPeerConn("nodeid", "127.163.0.1:2446"), }, @@ -106,12 +110,12 @@ func TestVerifyAddValidatorRequest(t *testing.T) { GenesisValidator: &launchtypes.GenesisValidator{ Address: "spn1dd246yq6z5vzjz9gh8cff46pll75yyl8c5tt7g", GenTx: gentx, - ConsPubKey: []byte("cosmos1gkheudhhjsvq0s8fxt7p6pwe0k3k30kepcnz9p="), + ConsPubKey: ed25519.PubKey("cosmos1gkheudhhjsvq0s8fxt7p6pwe0k3k30kepcnz9p="), SelfDelegation: sdk.NewCoin("stake", sdk.NewInt(95000000)), Peer: launchtypes.NewPeerConn("nodeid", "127.163.0.1:2446"), }, }, - want: fmt.Errorf("the consensus pub key cosmos1gkheudhhjsvq0s8fxt7p6pwe0k3k30kepcnz9p= doesn't match the one inside the gentx aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs="), + want: fmt.Errorf("the consensus pub key PubKeyEd25519{636F736D6F7331676B6865756468686A737671307338667874377036707765306B336B33306B6570636E7A39703D} doesn't match the one inside the gentx PubKeyEd25519{69E40B0893A35D4C81EDEBCEA1D23899BAEC848B77BE11C69727090DB52468CB}"), }, { name: "invalid validator address", @@ -119,7 +123,7 @@ func TestVerifyAddValidatorRequest(t *testing.T) { GenesisValidator: &launchtypes.GenesisValidator{ Address: "spn1gkheudhhjsvq0s8fxt7p6pwe0k3k30keaytytm", GenTx: gentx, - ConsPubKey: []byte("aeQLCJOjXUyB7evOodI4mbrshIt3vhHGlycJDbUkaMs="), + ConsPubKey: ed25519.PubKey(pk), SelfDelegation: sdk.NewCoin("stake", sdk.NewInt(95000000)), Peer: launchtypes.NewPeerConn("nodeid", "127.163.0.1:2446"), }, From 22a98a44ccdd476d25a946dce5b0c651f10ea273 Mon Sep 17 00:00:00 2001 From: Danilo Pantani Date: Tue, 10 May 2022 17:16:33 -0300 Subject: [PATCH 2/8] docs: change starport names to ignite (#2450) --- ignite/cmd/scaffold.go | 5 +++-- ignite/pkg/nodetime/nodetime.go | 4 ++-- ignite/services/chain/init.go | 2 +- ignite/services/chain/serve.go | 2 +- ignite/services/network/campaign.go | 6 +++--- ignite/services/network/queries.go | 4 ++-- ignite/services/scaffolder/init.go | 2 +- ignite/services/scaffolder/scaffolder.go | 4 ++-- ignite/templates/field/parse.go | 2 +- ignite/version/version.go | 6 +++--- 10 files changed, 19 insertions(+), 18 deletions(-) diff --git a/ignite/cmd/scaffold.go b/ignite/cmd/scaffold.go index 9d8ab21c2c..95b8c6598a 100644 --- a/ignite/cmd/scaffold.go +++ b/ignite/cmd/scaffold.go @@ -5,12 +5,13 @@ import ( "fmt" "github.com/AlecAivazis/survey/v2" + "github.com/spf13/cobra" + flag "github.com/spf13/pflag" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/pkg/xgit" "github.com/ignite-hq/cli/ignite/services/scaffolder" - "github.com/spf13/cobra" - flag "github.com/spf13/pflag" ) // flags related to component scaffolding diff --git a/ignite/pkg/nodetime/nodetime.go b/ignite/pkg/nodetime/nodetime.go index 0095987bab..1e4afb7629 100644 --- a/ignite/pkg/nodetime/nodetime.go +++ b/ignite/pkg/nodetime/nodetime.go @@ -1,6 +1,6 @@ // Package nodetime provides a single, and standalone NodeJS runtime executable that contains // several NodeJS CLI programs bundled inside where those are reachable via subcommands. -// the CLI bundled programs are the ones that needed by Starport and more can added as needed. +// the CLI bundled programs are the ones that needed by Ignite CLI and more can added as needed. package nodetime import ( @@ -31,7 +31,7 @@ const ( // CommandIBCRelayer is https://github.com/confio/ts-relayer/blob/main/spec/ibc-relayer.md. CommandIBCRelayer = "ibc-relayer" - // CommandXRelayer is a relayer wrapper for Starport made using the confio relayer. + // CommandXRelayer is a relayer wrapper for Ignite CLI made using the confio relayer. CommandXRelayer = "xrelayer" ) diff --git a/ignite/services/chain/init.go b/ignite/services/chain/init.go index 83bb33f68b..83ecdd2733 100644 --- a/ignite/services/chain/init.go +++ b/ignite/services/chain/init.go @@ -66,7 +66,7 @@ func (c *Chain) InitChain(ctx context.Context) error { return err } - // overwrite configuration changes from Starport's config.yml to + // overwrite configuration changes from Ignite CLI's config.yml to // over app's sdk configs. if err := c.plugin.Configure(home, conf); err != nil { diff --git a/ignite/services/chain/serve.go b/ignite/services/chain/serve.go index 99dc4754aa..55a589e87a 100644 --- a/ignite/services/chain/serve.go +++ b/ignite/services/chain/serve.go @@ -178,7 +178,7 @@ func (c *Chain) Serve(ctx context.Context, options ...ServeOption) error { // We suggest the user to eventually reset the app state if parsedErr == "" { fmt.Fprintf(c.stdLog().out, "%s %s\n", infoColor(`Blockchain failed to start. -If the new code is no longer compatible with the saved state, you can reset the database by launching:`), "starport chain serve --reset-once") +If the new code is no longer compatible with the saved state, you can reset the database by launching:`), "ignite chain serve --reset-once") return fmt.Errorf("cannot run %s", startErr.AppName) } diff --git a/ignite/services/network/campaign.go b/ignite/services/network/campaign.go index 8717103d72..f5931823f3 100644 --- a/ignite/services/network/campaign.go +++ b/ignite/services/network/campaign.go @@ -44,7 +44,7 @@ func WithCampaignTotalSupply(totalSupply sdk.Coins) Prop { } } -// Campaign fetches the campaign from Starport Network +// Campaign fetches the campaign from Network func (n Network) Campaign(ctx context.Context, campaignID uint64) (networktypes.Campaign, error) { n.ev.Send(events.New(events.StatusOngoing, "Fetching campaign information")) res, err := n.campaignQuery.Campaign(ctx, &campaigntypes.QueryGetCampaignRequest{ @@ -56,7 +56,7 @@ func (n Network) Campaign(ctx context.Context, campaignID uint64) (networktypes. return networktypes.ToCampaign(res.Campaign), nil } -// Campaigns fetches the campaigns from Starport Network +// Campaigns fetches the campaigns from Network func (n Network) Campaigns(ctx context.Context) ([]networktypes.Campaign, error) { var campaigns []networktypes.Campaign @@ -75,7 +75,7 @@ func (n Network) Campaigns(ctx context.Context) ([]networktypes.Campaign, error) return campaigns, nil } -// CreateCampaign creates a campaign in Starport Network +// CreateCampaign creates a campaign in Network func (n Network) CreateCampaign(name, metadata string, totalSupply sdk.Coins) (uint64, error) { n.ev.Send(events.New(events.StatusOngoing, fmt.Sprintf("Creating campaign %s", name))) diff --git a/ignite/services/network/queries.go b/ignite/services/network/queries.go index 71c9727fcf..1adb4f4e4e 100644 --- a/ignite/services/network/queries.go +++ b/ignite/services/network/queries.go @@ -21,7 +21,7 @@ var ( ErrObjectNotFound = errors.New("query object not found") ) -// ChainLaunch fetches the chain launch from Starport Network by launch id. +// ChainLaunch fetches the chain launch from Network by launch id. func (n Network) ChainLaunch(ctx context.Context, id uint64) (networktypes.ChainLaunch, error) { n.ev.Send(events.New(events.StatusOngoing, "Fetching chain information")) @@ -38,7 +38,7 @@ func (n Network) ChainLaunch(ctx context.Context, id uint64) (networktypes.Chain return networktypes.ToChainLaunch(res.Chain), nil } -// ChainLaunchesWithReward fetches the chain launches with rewards from Starport Network +// ChainLaunchesWithReward fetches the chain launches with rewards from Network func (n Network) ChainLaunchesWithReward(ctx context.Context) ([]networktypes.ChainLaunch, error) { g, ctx := errgroup.WithContext(ctx) diff --git a/ignite/services/scaffolder/init.go b/ignite/services/scaffolder/init.go index 91d477b3d2..c18c93c44e 100644 --- a/ignite/services/scaffolder/init.go +++ b/ignite/services/scaffolder/init.go @@ -21,7 +21,7 @@ import ( ) var ( - commitMessage = "Initialized with Starport" + commitMessage = "Initialized with Ignite CLI" devXAuthor = &object.Signature{ Name: "Developer Experience team at Tendermint", Email: "hello@tendermint.com", diff --git a/ignite/services/scaffolder/scaffolder.go b/ignite/services/scaffolder/scaffolder.go index 473040e599..c91e463f71 100644 --- a/ignite/services/scaffolder/scaffolder.go +++ b/ignite/services/scaffolder/scaffolder.go @@ -1,4 +1,4 @@ -// Package scaffolder initializes Starport apps and modifies existing ones +// Package scaffolder initializes Ignite CLI apps and modifies existing ones // to add more features in a later time. package scaffolder @@ -19,7 +19,7 @@ import ( "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" ) -// Scaffolder is Starport app scaffolder. +// Scaffolder is Ignite CLI app scaffolder. type Scaffolder struct { // path of the app. path string diff --git a/ignite/templates/field/parse.go b/ignite/templates/field/parse.go index 456cba3396..b7c5030dfc 100644 --- a/ignite/templates/field/parse.go +++ b/ignite/templates/field/parse.go @@ -8,7 +8,7 @@ import ( "github.com/ignite-hq/cli/ignite/templates/field/datatype" ) -// validateField validates the field Name and type, and checks the name is not forbidden by Starport +// validateField validates the field Name and type, and checks the name is not forbidden by Ignite CLI func validateField(field string, isForbiddenField func(string) error) (multiformatname.Name, datatype.Name, error) { fieldSplit := strings.Split(field, datatype.Separator) if len(fieldSplit) > 2 { diff --git a/ignite/version/version.go b/ignite/version/version.go index 8ff13d6043..642433985f 100644 --- a/ignite/version/version.go +++ b/ignite/version/version.go @@ -26,17 +26,17 @@ const ( const prefix = "v" var ( - // Version is the semantic version of Starport. + // Version is the semantic version of Ignite CLI. Version = versionDev - // Date is the build date of Starport. + // Date is the build date of Ignite CLI. Date = "-" // Head is the HEAD of the current branch. Head = "-" ) -// CheckNext checks whether there is a new version of Starport. +// CheckNext checks whether there is a new version of Ignite CLI. func CheckNext(ctx context.Context) (isAvailable bool, version string, err error) { if Version == versionDev || Version == versionNightly { return false, "", nil From ba62f885b41b8f47a781fedfb65d1e4905c2ec3b Mon Sep 17 00:00:00 2001 From: Danilo Pantani Date: Tue, 10 May 2022 17:44:20 -0300 Subject: [PATCH 3/8] feat(cmd/network): implement `client create` cmd (#2401) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add network connect command * add keyring flags and fix the pubkey encode * migrate ibc method to cosmoclient * move the command to `network client create` * apply comments suggestions from the PR and code quality * remove unused mocks * add cliui to network conenct command * fix pk encoding * converting to pk to proto * update mock and new node method name to `NewNodeClient` * fix pub key into the gentx parser * fix unit tests for ParseGentx test method * simplify code logic * fix unit tests * Apply suggestions from code review * refactor Co-authored-by: İlker G. Öztürk --- ignite/cmd/network.go | 1 + ignite/cmd/network_client.go | 20 + ignite/cmd/network_client_create.go | 67 +++ ignite/pkg/cosmosclient/cosmosclient.go | 65 +++ ignite/services/network/client.go | 32 ++ ignite/services/network/mocks/account_info.go | 14 +- .../services/network/mocks/campaign_client.go | 14 +- ignite/services/network/mocks/chain.go | 14 +- .../services/network/mocks/cosmos_client.go | 69 ++- .../services/network/mocks/launch_client.go | 14 +- .../services/network/mocks/profile_client.go | 14 +- .../services/network/mocks/reward_client.go | 14 +- .../services/network/mocks/staking_client.go | 446 ++++++++++++++++++ ignite/services/network/network.go | 3 + .../network/networktypes/chainlaunch.go | 40 +- ignite/services/network/node.go | 79 ++++ 16 files changed, 878 insertions(+), 28 deletions(-) create mode 100644 ignite/cmd/network_client.go create mode 100644 ignite/cmd/network_client_create.go create mode 100644 ignite/services/network/client.go create mode 100644 ignite/services/network/mocks/staking_client.go create mode 100644 ignite/services/network/node.go diff --git a/ignite/cmd/network.go b/ignite/cmd/network.go index 14c225dee2..fbad065f84 100644 --- a/ignite/cmd/network.go +++ b/ignite/cmd/network.go @@ -58,6 +58,7 @@ func NewNetwork() *cobra.Command { NewNetworkCampaign(), NewNetworkRequest(), NewNetworkReward(), + NewNetworkClient(), ) return c diff --git a/ignite/cmd/network_client.go b/ignite/cmd/network_client.go new file mode 100644 index 0000000000..400a826edc --- /dev/null +++ b/ignite/cmd/network_client.go @@ -0,0 +1,20 @@ +package ignitecmd + +import ( + "github.com/spf13/cobra" +) + +// NewNetworkClient creates a new client command that holds some other +// sub commands related to connect client to the network. +func NewNetworkClient() *cobra.Command { + c := &cobra.Command{ + Use: "client", + Short: "Connect your network with SPN", + } + + c.AddCommand( + NewNetworkClientCreate(), + ) + + return c +} diff --git a/ignite/cmd/network_client_create.go b/ignite/cmd/network_client_create.go new file mode 100644 index 0000000000..c038dd6579 --- /dev/null +++ b/ignite/cmd/network_client_create.go @@ -0,0 +1,67 @@ +package ignitecmd + +import ( + "github.com/spf13/cobra" + + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" + "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" + "github.com/ignite-hq/cli/ignite/services/network" +) + +// NewNetworkClientCreate connects the monitoring modules of launched chains with SPN +func NewNetworkClientCreate() *cobra.Command { + c := &cobra.Command{ + Use: "create [launch-id] [node-api-url]", + Short: "Connect the monitoring modules of launched chains with SPN", + Args: cobra.ExactArgs(2), + RunE: networkClientCreateHandler, + } + c.Flags().AddFlagSet(flagNetworkFrom()) + c.Flags().AddFlagSet(flagSetKeyringBackend()) + return c +} + +func networkClientCreateHandler(cmd *cobra.Command, args []string) error { + session := cliui.New() + defer session.Cleanup() + + launchID, err := network.ParseID(args[0]) + if err != nil { + return err + } + nodeAPI := args[1] + + nb, err := newNetworkBuilder(cmd) + if err != nil { + return err + } + + nodeClient, err := cosmosclient.New(cmd.Context(), cosmosclient.WithNodeAddress(nodeAPI)) + if err != nil { + return err + } + node, err := network.NewNodeClient(nodeClient) + if err != nil { + return err + } + + ibcInfo, err := node.IBCInfo(cmd.Context()) + if err != nil { + return err + } + + n, err := nb.Network() + if err != nil { + return err + } + + clientID, err := n.CreateClient(launchID, ibcInfo) + if err != nil { + return err + } + + session.StopSpinner() + session.Printf("%s Client created: %s\n", icons.Info, clientID) + return nil +} diff --git a/ignite/pkg/cosmosclient/cosmosclient.go b/ignite/pkg/cosmosclient/cosmosclient.go index 0864f0aaa0..2c7bb314db 100644 --- a/ignite/pkg/cosmosclient/cosmosclient.go +++ b/ignite/pkg/cosmosclient/cosmosclient.go @@ -3,6 +3,7 @@ package cosmosclient import ( "context" + "encoding/base64" "encoding/hex" "fmt" "io" @@ -26,10 +27,15 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" staking "github.com/cosmos/cosmos-sdk/x/staking/types" + commitmenttypes "github.com/cosmos/ibc-go/v2/modules/core/23-commitment/types" "github.com/gogo/protobuf/proto" prototypes "github.com/gogo/protobuf/types" "github.com/pkg/errors" + "github.com/tendermint/tendermint/libs/bytes" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" rpchttp "github.com/tendermint/tendermint/rpc/client/http" + ctypes "github.com/tendermint/tendermint/rpc/core/types" + tmtypes "github.com/tendermint/tendermint/types" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/cosmosfaucet" @@ -245,6 +251,65 @@ func (r Response) Decode(message proto.Message) error { }, message) } +// ConsensusInfo is the validator consensus info +type ConsensusInfo struct { + Timestamp string `json:"Timestamp"` + Root string `json:"Root"` + NextValidatorsHash string `json:"NextValidatorsHash"` + ValidatorSet *tmproto.ValidatorSet `json:"ValidatorSet"` +} + +// ConsensusInfo returns the appropriate tendermint consensus state by given height +// and the validator set for the next height +func (c Client) ConsensusInfo(ctx context.Context, height int64) (ConsensusInfo, error) { + node, err := c.Context().GetNode() + if err != nil { + return ConsensusInfo{}, err + } + + commit, err := node.Commit(ctx, &height) + if err != nil { + return ConsensusInfo{}, err + } + + var ( + page = 1 + count = 10_000 + ) + validators, err := node.Validators(ctx, &height, &page, &count) + if err != nil { + return ConsensusInfo{}, err + } + + protoValset, err := tmtypes.NewValidatorSet(validators.Validators).ToProto() + if err != nil { + return ConsensusInfo{}, err + } + + heightNext := height + 1 + validatorsNext, err := node.Validators(ctx, &heightNext, &page, &count) + if err != nil { + return ConsensusInfo{}, err + } + + var ( + hash = tmtypes.NewValidatorSet(validatorsNext.Validators).Hash() + root = commitmenttypes.NewMerkleRoot(commit.AppHash) + ) + + return ConsensusInfo{ + Timestamp: commit.Time.Format(time.RFC3339Nano), + NextValidatorsHash: bytes.HexBytes(hash).String(), + Root: base64.StdEncoding.EncodeToString(root.Hash), + ValidatorSet: protoValset, + }, nil +} + +// Status returns the node status +func (c Client) Status(ctx context.Context) (*ctypes.ResultStatus, error) { + return c.RPC.Status(ctx) +} + // BroadcastTx creates and broadcasts a tx with given messages for account. func (c Client) BroadcastTx(accountName string, msgs ...sdktypes.Msg) (Response, error) { _, broadcast, err := c.BroadcastTxWithProvision(accountName, msgs...) diff --git a/ignite/services/network/client.go b/ignite/services/network/client.go new file mode 100644 index 0000000000..7f1d2847bb --- /dev/null +++ b/ignite/services/network/client.go @@ -0,0 +1,32 @@ +package network + +import ( + monitoringctypes "github.com/tendermint/spn/x/monitoringc/types" + + "github.com/ignite-hq/cli/ignite/services/network/networktypes" +) + +func (n Network) CreateClient( + launchID uint64, + ibcInfo IBCInfo, +) (string, error) { + msgCreateClient := monitoringctypes.NewMsgCreateClient( + n.account.Address(networktypes.SPN), + launchID, + ibcInfo.ConsensusState, + ibcInfo.ValidatorSet, + ibcInfo.UnbondingTime, + ibcInfo.Height, + ) + + res, err := n.cosmos.BroadcastTx(n.account.Name, msgCreateClient) + if err != nil { + return "", err + } + + var createClientRes monitoringctypes.MsgCreateClientResponse + if err := res.Decode(&createClientRes); err != nil { + return "", err + } + return createClientRes.ClientID, nil +} diff --git a/ignite/services/network/mocks/account_info.go b/ignite/services/network/mocks/account_info.go index ad803a03c8..de4e0ad3ec 100644 --- a/ignite/services/network/mocks/account_info.go +++ b/ignite/services/network/mocks/account_info.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.12.2. DO NOT EDIT. package mocks @@ -10,6 +10,8 @@ import ( mock "github.com/stretchr/testify/mock" + testing "testing" + types "github.com/cosmos/cosmos-sdk/types" ) @@ -114,3 +116,13 @@ func (_m *AccountInfo) GetType() keyring.KeyType { return r0 } + +// NewAccountInfo creates a new instance of AccountInfo. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. +func NewAccountInfo(t testing.TB) *AccountInfo { + mock := &AccountInfo{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/ignite/services/network/mocks/campaign_client.go b/ignite/services/network/mocks/campaign_client.go index 4bda0a9ff1..b7a57a1bdf 100644 --- a/ignite/services/network/mocks/campaign_client.go +++ b/ignite/services/network/mocks/campaign_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.12.2. DO NOT EDIT. package mocks @@ -9,6 +9,8 @@ import ( mock "github.com/stretchr/testify/mock" + testing "testing" + types "github.com/tendermint/spn/x/campaign/types" ) @@ -346,3 +348,13 @@ func (_m *CampaignClient) TotalShares(ctx context.Context, in *types.QueryTotalS return r0, r1 } + +// NewCampaignClient creates a new instance of CampaignClient. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. +func NewCampaignClient(t testing.TB) *CampaignClient { + mock := &CampaignClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/ignite/services/network/mocks/chain.go b/ignite/services/network/mocks/chain.go index d7d6e8c0f7..1811ace0f5 100644 --- a/ignite/services/network/mocks/chain.go +++ b/ignite/services/network/mocks/chain.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.10.6. DO NOT EDIT. +// Code generated by mockery v2.12.2. DO NOT EDIT. package mocks @@ -6,6 +6,8 @@ import ( context "context" mock "github.com/stretchr/testify/mock" + + testing "testing" ) // Chain is an autogenerated mock type for the Chain type @@ -250,3 +252,13 @@ func (_m *Chain) SourceURL() string { return r0 } + +// NewChain creates a new instance of Chain. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. +func NewChain(t testing.TB) *Chain { + mock := &Chain{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/ignite/services/network/mocks/cosmos_client.go b/ignite/services/network/mocks/cosmos_client.go index 7660a3a4e8..1e38b204ae 100644 --- a/ignite/services/network/mocks/cosmos_client.go +++ b/ignite/services/network/mocks/cosmos_client.go @@ -1,14 +1,23 @@ -// Code generated by mockery v2.10.6. DO NOT EDIT. +// Code generated by mockery v2.12.2. DO NOT EDIT. package mocks import ( + context "context" + client "github.com/cosmos/cosmos-sdk/client" - types "github.com/cosmos/cosmos-sdk/types" - mock "github.com/stretchr/testify/mock" + + coretypes "github.com/tendermint/tendermint/rpc/core/types" cosmosaccount "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" + cosmosclient "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" + + mock "github.com/stretchr/testify/mock" + + testing "testing" + + types "github.com/cosmos/cosmos-sdk/types" ) // CosmosClient is an autogenerated mock type for the CosmosClient type @@ -125,6 +134,27 @@ func (_m *CosmosClient) BroadcastTxWithProvision(accountName string, msgs ...typ return r0, r1, r2 } +// ConsensusInfo provides a mock function with given fields: ctx, height +func (_m *CosmosClient) ConsensusInfo(ctx context.Context, height int64) (cosmosclient.ConsensusInfo, error) { + ret := _m.Called(ctx, height) + + var r0 cosmosclient.ConsensusInfo + if rf, ok := ret.Get(0).(func(context.Context, int64) cosmosclient.ConsensusInfo); ok { + r0 = rf(ctx, height) + } else { + r0 = ret.Get(0).(cosmosclient.ConsensusInfo) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok { + r1 = rf(ctx, height) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // Context provides a mock function with given fields: func (_m *CosmosClient) Context() client.Context { ret := _m.Called() @@ -138,3 +168,36 @@ func (_m *CosmosClient) Context() client.Context { return r0 } + +// Status provides a mock function with given fields: ctx +func (_m *CosmosClient) Status(ctx context.Context) (*coretypes.ResultStatus, error) { + ret := _m.Called(ctx) + + var r0 *coretypes.ResultStatus + if rf, ok := ret.Get(0).(func(context.Context) *coretypes.ResultStatus); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*coretypes.ResultStatus) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewCosmosClient creates a new instance of CosmosClient. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. +func NewCosmosClient(t testing.TB) *CosmosClient { + mock := &CosmosClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/ignite/services/network/mocks/launch_client.go b/ignite/services/network/mocks/launch_client.go index 83821be397..3bd699c535 100644 --- a/ignite/services/network/mocks/launch_client.go +++ b/ignite/services/network/mocks/launch_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.12.2. DO NOT EDIT. package mocks @@ -9,6 +9,8 @@ import ( mock "github.com/stretchr/testify/mock" + testing "testing" + types "github.com/tendermint/spn/x/launch/types" ) @@ -346,3 +348,13 @@ func (_m *LaunchClient) VestingAccountAll(ctx context.Context, in *types.QueryAl return r0, r1 } + +// NewLaunchClient creates a new instance of LaunchClient. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. +func NewLaunchClient(t testing.TB) *LaunchClient { + mock := &LaunchClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/ignite/services/network/mocks/profile_client.go b/ignite/services/network/mocks/profile_client.go index 68ead6cafb..f588da6c69 100644 --- a/ignite/services/network/mocks/profile_client.go +++ b/ignite/services/network/mocks/profile_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.12.2. DO NOT EDIT. package mocks @@ -9,6 +9,8 @@ import ( mock "github.com/stretchr/testify/mock" + testing "testing" + types "github.com/tendermint/spn/x/profile/types" ) @@ -196,3 +198,13 @@ func (_m *ProfileClient) ValidatorByOperatorAddress(ctx context.Context, in *typ return r0, r1 } + +// NewProfileClient creates a new instance of ProfileClient. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. +func NewProfileClient(t testing.TB) *ProfileClient { + mock := &ProfileClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/ignite/services/network/mocks/reward_client.go b/ignite/services/network/mocks/reward_client.go index 83810b40de..0d99445be0 100644 --- a/ignite/services/network/mocks/reward_client.go +++ b/ignite/services/network/mocks/reward_client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.10.0. DO NOT EDIT. +// Code generated by mockery v2.12.2. DO NOT EDIT. package mocks @@ -9,6 +9,8 @@ import ( mock "github.com/stretchr/testify/mock" + testing "testing" + types "github.com/tendermint/spn/x/reward/types" ) @@ -106,3 +108,13 @@ func (_m *RewardClient) RewardPoolAll(ctx context.Context, in *types.QueryAllRew return r0, r1 } + +// NewRewardClient creates a new instance of RewardClient. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. +func NewRewardClient(t testing.TB) *RewardClient { + mock := &RewardClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/ignite/services/network/mocks/staking_client.go b/ignite/services/network/mocks/staking_client.go new file mode 100644 index 0000000000..a323ab6cc4 --- /dev/null +++ b/ignite/services/network/mocks/staking_client.go @@ -0,0 +1,446 @@ +// Code generated by mockery v2.11.0. DO NOT EDIT. + +package mocks + +import ( + "context" + "testing" + + "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/stretchr/testify/mock" + "google.golang.org/grpc" +) + +// StakingClient is an autogenerated mock type for the StakingClient type +type StakingClient struct { + mock.Mock +} + +// Delegation provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) Delegation(ctx context.Context, in *types.QueryDelegationRequest, opts ...grpc.CallOption) (*types.QueryDelegationResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryDelegationResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryDelegationRequest, ...grpc.CallOption) *types.QueryDelegationResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryDelegationResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryDelegationRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DelegatorDelegations provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) DelegatorDelegations(ctx context.Context, in *types.QueryDelegatorDelegationsRequest, opts ...grpc.CallOption) (*types.QueryDelegatorDelegationsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryDelegatorDelegationsResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryDelegatorDelegationsRequest, ...grpc.CallOption) *types.QueryDelegatorDelegationsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryDelegatorDelegationsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryDelegatorDelegationsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DelegatorUnbondingDelegations provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) DelegatorUnbondingDelegations(ctx context.Context, in *types.QueryDelegatorUnbondingDelegationsRequest, opts ...grpc.CallOption) (*types.QueryDelegatorUnbondingDelegationsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryDelegatorUnbondingDelegationsResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryDelegatorUnbondingDelegationsRequest, ...grpc.CallOption) *types.QueryDelegatorUnbondingDelegationsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryDelegatorUnbondingDelegationsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryDelegatorUnbondingDelegationsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DelegatorValidator provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) DelegatorValidator(ctx context.Context, in *types.QueryDelegatorValidatorRequest, opts ...grpc.CallOption) (*types.QueryDelegatorValidatorResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryDelegatorValidatorResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryDelegatorValidatorRequest, ...grpc.CallOption) *types.QueryDelegatorValidatorResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryDelegatorValidatorResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryDelegatorValidatorRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DelegatorValidators provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) DelegatorValidators(ctx context.Context, in *types.QueryDelegatorValidatorsRequest, opts ...grpc.CallOption) (*types.QueryDelegatorValidatorsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryDelegatorValidatorsResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryDelegatorValidatorsRequest, ...grpc.CallOption) *types.QueryDelegatorValidatorsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryDelegatorValidatorsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryDelegatorValidatorsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// HistoricalInfo provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) HistoricalInfo(ctx context.Context, in *types.QueryHistoricalInfoRequest, opts ...grpc.CallOption) (*types.QueryHistoricalInfoResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryHistoricalInfoResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryHistoricalInfoRequest, ...grpc.CallOption) *types.QueryHistoricalInfoResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryHistoricalInfoResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryHistoricalInfoRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Params provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) Params(ctx context.Context, in *types.QueryParamsRequest, opts ...grpc.CallOption) (*types.QueryParamsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryParamsResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) *types.QueryParamsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryParamsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Pool provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) Pool(ctx context.Context, in *types.QueryPoolRequest, opts ...grpc.CallOption) (*types.QueryPoolResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryPoolResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryPoolRequest, ...grpc.CallOption) *types.QueryPoolResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryPoolResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryPoolRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Redelegations provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) Redelegations(ctx context.Context, in *types.QueryRedelegationsRequest, opts ...grpc.CallOption) (*types.QueryRedelegationsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryRedelegationsResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryRedelegationsRequest, ...grpc.CallOption) *types.QueryRedelegationsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryRedelegationsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryRedelegationsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UnbondingDelegation provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) UnbondingDelegation(ctx context.Context, in *types.QueryUnbondingDelegationRequest, opts ...grpc.CallOption) (*types.QueryUnbondingDelegationResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryUnbondingDelegationResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryUnbondingDelegationRequest, ...grpc.CallOption) *types.QueryUnbondingDelegationResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryUnbondingDelegationResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryUnbondingDelegationRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Validator provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) Validator(ctx context.Context, in *types.QueryValidatorRequest, opts ...grpc.CallOption) (*types.QueryValidatorResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryValidatorResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryValidatorRequest, ...grpc.CallOption) *types.QueryValidatorResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryValidatorResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryValidatorRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ValidatorDelegations provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) ValidatorDelegations(ctx context.Context, in *types.QueryValidatorDelegationsRequest, opts ...grpc.CallOption) (*types.QueryValidatorDelegationsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryValidatorDelegationsResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryValidatorDelegationsRequest, ...grpc.CallOption) *types.QueryValidatorDelegationsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryValidatorDelegationsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryValidatorDelegationsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ValidatorUnbondingDelegations provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) ValidatorUnbondingDelegations(ctx context.Context, in *types.QueryValidatorUnbondingDelegationsRequest, opts ...grpc.CallOption) (*types.QueryValidatorUnbondingDelegationsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryValidatorUnbondingDelegationsResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryValidatorUnbondingDelegationsRequest, ...grpc.CallOption) *types.QueryValidatorUnbondingDelegationsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryValidatorUnbondingDelegationsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryValidatorUnbondingDelegationsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Validators provides a mock function with given fields: ctx, in, opts +func (_m *StakingClient) Validators(ctx context.Context, in *types.QueryValidatorsRequest, opts ...grpc.CallOption) (*types.QueryValidatorsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryValidatorsResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryValidatorsRequest, ...grpc.CallOption) *types.QueryValidatorsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryValidatorsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryValidatorsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewQueryClient creates a new instance of StakingClient. It also registers a cleanup function to assert the mocks expectations. +func NewQueryClient(t testing.TB) *StakingClient { + mock := &StakingClient{} + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/ignite/services/network/network.go b/ignite/services/network/network.go index 2384a49d7b..db2b11e2df 100644 --- a/ignite/services/network/network.go +++ b/ignite/services/network/network.go @@ -11,6 +11,7 @@ import ( launchtypes "github.com/tendermint/spn/x/launch/types" profiletypes "github.com/tendermint/spn/x/profile/types" rewardtypes "github.com/tendermint/spn/x/reward/types" + ctypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" @@ -24,6 +25,8 @@ type CosmosClient interface { Context() client.Context BroadcastTx(accountName string, msgs ...sdktypes.Msg) (cosmosclient.Response, error) BroadcastTxWithProvision(accountName string, msgs ...sdktypes.Msg) (gas uint64, broadcast func() (cosmosclient.Response, error), err error) + Status(ctx context.Context) (*ctypes.ResultStatus, error) + ConsensusInfo(ctx context.Context, height int64) (cosmosclient.ConsensusInfo, error) } // Network is network builder. diff --git a/ignite/services/network/networktypes/chainlaunch.go b/ignite/services/network/networktypes/chainlaunch.go index 45dd33156e..82deea657c 100644 --- a/ignite/services/network/networktypes/chainlaunch.go +++ b/ignite/services/network/networktypes/chainlaunch.go @@ -7,17 +7,18 @@ type ( // ChainLaunch represents the launch of a chain on SPN ChainLaunch struct { - ID uint64 `json:"ID"` - ChainID string `json:"ChainID"` - SourceURL string `json:"SourceURL"` - SourceHash string `json:"SourceHash"` - GenesisURL string `json:"GenesisURL"` - GenesisHash string `json:"GenesisHash"` - LaunchTime int64 `json:"LaunchTime"` - CampaignID uint64 `json:"CampaignID"` - LaunchTriggered bool `json:"LaunchTriggered"` - Network NetworkType `json:"Network"` - Reward string `json:"Reward,omitempty"` + ID uint64 `json:"ID"` + ConsumerRevisionHeight int64 `json:"ConsumerRevisionHeight"` + ChainID string `json:"ChainID"` + SourceURL string `json:"SourceURL"` + SourceHash string `json:"SourceHash"` + GenesisURL string `json:"GenesisURL"` + GenesisHash string `json:"GenesisHash"` + LaunchTime int64 `json:"LaunchTime"` + CampaignID uint64 `json:"CampaignID"` + LaunchTriggered bool `json:"LaunchTriggered"` + Network NetworkType `json:"Network"` + Reward string `json:"Reward,omitempty"` } ) @@ -43,14 +44,15 @@ func ToChainLaunch(chain launchtypes.Chain) ChainLaunch { } launch := ChainLaunch{ - ID: chain.LaunchID, - ChainID: chain.GenesisChainID, - SourceURL: chain.SourceURL, - SourceHash: chain.SourceHash, - LaunchTime: launchTime, - CampaignID: chain.CampaignID, - LaunchTriggered: chain.LaunchTriggered, - Network: network, + ID: chain.LaunchID, + ConsumerRevisionHeight: chain.ConsumerRevisionHeight, + ChainID: chain.GenesisChainID, + SourceURL: chain.SourceURL, + SourceHash: chain.SourceHash, + LaunchTime: launchTime, + CampaignID: chain.CampaignID, + LaunchTriggered: chain.LaunchTriggered, + Network: network, } // check if custom genesis URL is provided. diff --git a/ignite/services/network/node.go b/ignite/services/network/node.go new file mode 100644 index 0000000000..87ca822b00 --- /dev/null +++ b/ignite/services/network/node.go @@ -0,0 +1,79 @@ +package network + +import ( + "context" + "encoding/base64" + + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + spntypes "github.com/tendermint/spn/pkg/types" +) + +// Node is node builder. +type Node struct { + cosmos CosmosClient + stakingQuery stakingtypes.QueryClient +} + +// IBCInfo is node client info. +type IBCInfo struct { + ConsensusState spntypes.ConsensusState + ValidatorSet spntypes.ValidatorSet + UnbondingTime int64 + Height uint64 +} + +func NewNodeClient(cosmos CosmosClient) (Node, error) { + return Node{ + cosmos: cosmos, + stakingQuery: stakingtypes.NewQueryClient(cosmos.Context()), + }, nil +} + +// IBCInfo Fetches the consensus state, validator set and the staking parameters +func (n Node) IBCInfo(ctx context.Context) (IBCInfo, error) { + status, err := n.cosmos.Status(ctx) + if err != nil { + return IBCInfo{}, err + } + lastBlockHeight := status.SyncInfo.LatestBlockHeight + + consensusState, err := n.cosmos.ConsensusInfo(ctx, lastBlockHeight) + if err != nil { + return IBCInfo{}, err + } + spnConsensusStatue := spntypes.NewConsensusState( + consensusState.Timestamp, + consensusState.NextValidatorsHash, + consensusState.Root, + ) + + validators := make([]spntypes.Validator, len(consensusState.ValidatorSet.Validators)) + for i, validator := range consensusState.ValidatorSet.Validators { + validators[i] = spntypes.NewValidator( + base64.StdEncoding.EncodeToString(validator.PubKey.GetEd25519()), + validator.ProposerPriority, + validator.VotingPower, + ) + } + + stakingParams, err := n.StakingParams(ctx) + if err != nil { + return IBCInfo{}, err + } + + return IBCInfo{ + ConsensusState: spnConsensusStatue, + ValidatorSet: spntypes.NewValidatorSet(validators...), + UnbondingTime: int64(stakingParams.UnbondingTime.Seconds()), + Height: uint64(lastBlockHeight), + }, nil +} + +// StakingParams fetches the staking module params +func (n Node) StakingParams(ctx context.Context) (stakingtypes.Params, error) { + res, err := n.stakingQuery.Params(ctx, &stakingtypes.QueryParamsRequest{}) + if err != nil { + return stakingtypes.Params{}, err + } + return res.Params, nil +} From c40cc41d615b48656b33dde74614d90485c21edf Mon Sep 17 00:00:00 2001 From: Danilo Pantani Date: Thu, 12 May 2022 16:04:58 -0300 Subject: [PATCH 4/8] feat(network): update spn and mocks (#2466) * update spn and mocks * update spn version --- go.mod | 5 ++- go.sum | 17 ++++--- ignite/services/network/mocks/account_info.go | 15 +++---- .../services/network/mocks/campaign_client.go | 45 +++++++++++++++---- ignite/services/network/mocks/chain.go | 7 ++- .../services/network/mocks/cosmos_client.go | 19 +++----- .../services/network/mocks/launch_client.go | 13 +++--- .../services/network/mocks/profile_client.go | 13 +++--- .../services/network/mocks/reward_client.go | 13 +++--- ignite/templates/app/stargate/go.mod.plush | 2 +- ignite/templates/app/stargate/go.sum | 17 ++++--- 11 files changed, 87 insertions(+), 79 deletions(-) diff --git a/go.mod b/go.mod index 3936177a68..473ba05980 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/stretchr/testify v1.7.1 github.com/takuoki/gocase v1.0.0 github.com/tendermint/flutter/v2 v2.0.3 - github.com/tendermint/spn v0.2.1-0.20220427143342-de7398284030 + github.com/tendermint/spn v0.2.1-0.20220511154430-aeab7a5b2bc0 github.com/tendermint/tendermint v0.34.19 github.com/tendermint/tm-db v0.6.7 github.com/tendermint/vue v0.3.5 @@ -84,7 +84,7 @@ require ( github.com/chris-ramon/douceur v0.2.0 // indirect github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect github.com/coinbase/rosetta-sdk-go v0.7.0 // indirect - github.com/confio/ics23/go v0.6.6 // indirect + github.com/confio/ics23/go v0.7.0 // indirect github.com/containerd/cgroups v1.0.3 // indirect github.com/containerd/console v1.0.3 // indirect github.com/containerd/containerd v1.6.2 // indirect @@ -215,6 +215,7 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // 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.0 // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce // indirect github.com/xanzy/ssh-agent v0.2.1 // indirect diff --git a/go.sum b/go.sum index 28f69da601..d7339d8d14 100644 --- a/go.sum +++ b/go.sum @@ -307,8 +307,9 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE github.com/coinbase/rosetta-sdk-go v0.6.10/go.mod h1:J/JFMsfcePrjJZkwQFLh+hJErkAmdm9Iyy3D5Y0LfXo= github.com/coinbase/rosetta-sdk-go v0.7.0 h1:lmTO/JEpCvZgpbkOITL95rA80CPKb5CtMzLaqF2mCNg= github.com/coinbase/rosetta-sdk-go v0.7.0/go.mod h1:7nD3oBPIiHqhRprqvMgPoGxe/nyq3yftRmpsy29coWE= -github.com/confio/ics23/go v0.6.6 h1:pkOy18YxxJ/r0XFDCnrl4Bjv6h4LkBSpLS6F38mrKL8= github.com/confio/ics23/go v0.6.6/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= +github.com/confio/ics23/go v0.7.0 h1:00d2kukk7sPoHWL4zZBZwzxnpA2pec1NPdwbSokJ5w8= +github.com/confio/ics23/go v0.7.0/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= @@ -422,8 +423,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44= github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU= github.com/cosmos/cosmos-sdk v0.44.5/go.mod h1:maUA6m2TBxOJZkbwl0eRtEBgTX37kcaiOWU5t1HEGaY= -github.com/cosmos/cosmos-sdk v0.45.3 h1:PiVSU3IkNEDPhoxOZHk2lPnhwBBJgEYAtAR0jGXRN4g= -github.com/cosmos/cosmos-sdk v0.45.3/go.mod h1:qYm5JEr0ZlbnmoP/Q3b+dYMOliHf4ddHirpILiwZzqg= github.com/cosmos/cosmos-sdk v0.45.4 h1:eStDAhJdMY8n5arbBRe+OwpNeBSunxSBHp1g55ulfdA= github.com/cosmos/cosmos-sdk v0.45.4/go.mod h1:WOqtDxN3eCCmnYLVla10xG7lEXkFjpTaqm2a2WasgCc= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= @@ -567,8 +566,8 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/gin-gonic/gin v1.7.0 h1:jGB9xAJQ12AIGNB4HguylppmDK1Am9ppF7XnGXXJuoU= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= @@ -735,8 +734,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/go-github/v37 v37.0.0 h1:rCspN8/6kB1BAJWZfuafvHhyfIo5fkAulaP/3bOQ/tM= github.com/google/go-github/v37 v37.0.0/go.mod h1:LM7in3NmXDrX58GbEHy7FtNLbI2JijX93RnMKvWG3m4= @@ -1484,11 +1483,12 @@ github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RM github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= github.com/tendermint/flutter/v2 v2.0.3 h1:+J3Q6FRdcDTLkrcPQHY306J7wRPEKxfU2K2xCVFJGqs= github.com/tendermint/flutter/v2 v2.0.3/go.mod h1:hnaVhWhzv2Od1LqZFWrRKwiOHeMonsB9EIWP0AGMPw0= -github.com/tendermint/fundraising v0.2.0 h1:V6N7u/oWXjQZEbXXk34uAfijYnYQFZrZGA39e03UFz8= +github.com/tendermint/fundraising v0.3.0 h1:VtHfmVlAS93MUDlt6Em21l3taw6s9kLY/w8Cd1FB9fM= +github.com/tendermint/fundraising v0.3.0/go.mod h1:oJFZUZ/GsACtkYeWScKpHLdqMUThNWpMAi/G47LJUi4= 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.20220427143342-de7398284030 h1:1S5urE/lHktsawx/I4r6iHiV1Ylfhp8mQZ5eQKbY1bA= -github.com/tendermint/spn v0.2.1-0.20220427143342-de7398284030/go.mod h1:9wXyogMDn9fK85s+bSADy+wvZ27DjLEByByMM+0O6NU= +github.com/tendermint/spn v0.2.1-0.20220511154430-aeab7a5b2bc0 h1:kIjnfHO472W2WSzul3ek3p07yKVYxSFUNng4YJmVex4= +github.com/tendermint/spn v0.2.1-0.20220511154430-aeab7a5b2bc0/go.mod h1:xNtBc/jmB1pvb+EJYQtyJdcTZM9dOhJeW3C4Qj9n7tg= github.com/tendermint/tendermint v0.34.14/go.mod h1:FrwVm3TvsVicI9Z7FlucHV6Znfd5KBc/Lpp69cCwtk0= github.com/tendermint/tendermint v0.34.19 h1:y0P1qI5wSa9IRuhKnTDA6IUcOrLi1hXJuALR+R7HFEk= github.com/tendermint/tendermint v0.34.19/go.mod h1:R5+wgIwSxMdKQcmOaeudL0Cjkr3HDkhpcdum6VeU3R4= @@ -2155,7 +2155,6 @@ google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e h1:fNKDNuUyC4WH+inqDMpfXDdfvwfYILbsX+oskGZ8hxg= google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= diff --git a/ignite/services/network/mocks/account_info.go b/ignite/services/network/mocks/account_info.go index de4e0ad3ec..ddb063d1fd 100644 --- a/ignite/services/network/mocks/account_info.go +++ b/ignite/services/network/mocks/account_info.go @@ -3,16 +3,13 @@ package mocks import ( - hd "github.com/cosmos/cosmos-sdk/crypto/hd" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - - keyring "github.com/cosmos/cosmos-sdk/crypto/keyring" - - mock "github.com/stretchr/testify/mock" + "testing" - testing "testing" - - types "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/mock" ) // AccountInfo is an autogenerated mock type for the AccountInfo type diff --git a/ignite/services/network/mocks/campaign_client.go b/ignite/services/network/mocks/campaign_client.go index b7a57a1bdf..a482fe88f4 100644 --- a/ignite/services/network/mocks/campaign_client.go +++ b/ignite/services/network/mocks/campaign_client.go @@ -3,22 +3,49 @@ package mocks import ( - context "context" + "context" + "testing" - grpc "google.golang.org/grpc" - - mock "github.com/stretchr/testify/mock" - - testing "testing" - - types "github.com/tendermint/spn/x/campaign/types" + "github.com/stretchr/testify/mock" + "github.com/tendermint/spn/x/campaign/types" + "google.golang.org/grpc" ) -// CampaignClient is an autogenerated mock type for the CampaignClient type +// CampaignClient is an autogenerated mock type for the QueryClient type type CampaignClient struct { mock.Mock } +// AuctionsOfCampaign provides a mock function with given fields: ctx, in, opts +func (_m *CampaignClient) AuctionsOfCampaign(ctx context.Context, in *types.QueryAuctionsOfCampaignRequest, opts ...grpc.CallOption) (*types.QueryAuctionsOfCampaignResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryAuctionsOfCampaignResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryAuctionsOfCampaignRequest, ...grpc.CallOption) *types.QueryAuctionsOfCampaignResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryAuctionsOfCampaignResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryAuctionsOfCampaignRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // Campaign provides a mock function with given fields: ctx, in, opts func (_m *CampaignClient) Campaign(ctx context.Context, in *types.QueryGetCampaignRequest, opts ...grpc.CallOption) (*types.QueryGetCampaignResponse, error) { _va := make([]interface{}, len(opts)) diff --git a/ignite/services/network/mocks/chain.go b/ignite/services/network/mocks/chain.go index 1811ace0f5..9ff3b873ee 100644 --- a/ignite/services/network/mocks/chain.go +++ b/ignite/services/network/mocks/chain.go @@ -3,11 +3,10 @@ package mocks import ( - context "context" + "context" + "testing" - mock "github.com/stretchr/testify/mock" - - testing "testing" + "github.com/stretchr/testify/mock" ) // Chain is an autogenerated mock type for the Chain type diff --git a/ignite/services/network/mocks/cosmos_client.go b/ignite/services/network/mocks/cosmos_client.go index 1e38b204ae..02d1fb8353 100644 --- a/ignite/services/network/mocks/cosmos_client.go +++ b/ignite/services/network/mocks/cosmos_client.go @@ -3,21 +3,16 @@ package mocks import ( - context "context" - - client "github.com/cosmos/cosmos-sdk/client" + "context" + "testing" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/mock" coretypes "github.com/tendermint/tendermint/rpc/core/types" - cosmosaccount "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" - - cosmosclient "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" - - mock "github.com/stretchr/testify/mock" - - testing "testing" - - types "github.com/cosmos/cosmos-sdk/types" + "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" + "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" ) // CosmosClient is an autogenerated mock type for the CosmosClient type diff --git a/ignite/services/network/mocks/launch_client.go b/ignite/services/network/mocks/launch_client.go index 3bd699c535..cc9a174f8e 100644 --- a/ignite/services/network/mocks/launch_client.go +++ b/ignite/services/network/mocks/launch_client.go @@ -3,15 +3,12 @@ package mocks import ( - context "context" + "context" + "testing" - grpc "google.golang.org/grpc" - - mock "github.com/stretchr/testify/mock" - - testing "testing" - - types "github.com/tendermint/spn/x/launch/types" + "github.com/stretchr/testify/mock" + "github.com/tendermint/spn/x/launch/types" + "google.golang.org/grpc" ) // LaunchClient is an autogenerated mock type for the LaunchClient type diff --git a/ignite/services/network/mocks/profile_client.go b/ignite/services/network/mocks/profile_client.go index f588da6c69..b2b3eb96c1 100644 --- a/ignite/services/network/mocks/profile_client.go +++ b/ignite/services/network/mocks/profile_client.go @@ -3,15 +3,12 @@ package mocks import ( - context "context" + "context" + "testing" - grpc "google.golang.org/grpc" - - mock "github.com/stretchr/testify/mock" - - testing "testing" - - types "github.com/tendermint/spn/x/profile/types" + "github.com/stretchr/testify/mock" + "github.com/tendermint/spn/x/profile/types" + "google.golang.org/grpc" ) // ProfileClient is an autogenerated mock type for the ProfileClient type diff --git a/ignite/services/network/mocks/reward_client.go b/ignite/services/network/mocks/reward_client.go index 0d99445be0..1169d355cd 100644 --- a/ignite/services/network/mocks/reward_client.go +++ b/ignite/services/network/mocks/reward_client.go @@ -3,15 +3,12 @@ package mocks import ( - context "context" + "context" + "testing" - grpc "google.golang.org/grpc" - - mock "github.com/stretchr/testify/mock" - - testing "testing" - - types "github.com/tendermint/spn/x/reward/types" + "github.com/stretchr/testify/mock" + "github.com/tendermint/spn/x/reward/types" + "google.golang.org/grpc" ) // RewardClient is an autogenerated mock type for the RewardClient type diff --git a/ignite/templates/app/stargate/go.mod.plush b/ignite/templates/app/stargate/go.mod.plush index a9adcea440..a8df22af8a 100644 --- a/ignite/templates/app/stargate/go.mod.plush +++ b/ignite/templates/app/stargate/go.mod.plush @@ -13,7 +13,7 @@ require ( github.com/spf13/cast v1.4.1 github.com/spf13/cobra v1.4.0 github.com/stretchr/testify v1.7.1 - github.com/tendermint/spn v0.2.1-0.20220427143342-de7398284030 + github.com/tendermint/spn v0.2.1-0.20220511154430-aeab7a5b2bc0 github.com/tendermint/tendermint v0.34.19 github.com/tendermint/tm-db v0.6.7 google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e diff --git a/ignite/templates/app/stargate/go.sum b/ignite/templates/app/stargate/go.sum index cf549d4cc6..f7eb5292ee 100644 --- a/ignite/templates/app/stargate/go.sum +++ b/ignite/templates/app/stargate/go.sum @@ -335,8 +335,9 @@ github.com/coinbase/rosetta-sdk-go v0.7.0 h1:lmTO/JEpCvZgpbkOITL95rA80CPKb5CtMzL github.com/coinbase/rosetta-sdk-go v0.7.0/go.mod h1:7nD3oBPIiHqhRprqvMgPoGxe/nyq3yftRmpsy29coWE= github.com/confio/ics23/go v0.0.0-20200817220745-f173e6211efb/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/confio/ics23/go v0.6.3/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= -github.com/confio/ics23/go v0.6.6 h1:pkOy18YxxJ/r0XFDCnrl4Bjv6h4LkBSpLS6F38mrKL8= github.com/confio/ics23/go v0.6.6/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= +github.com/confio/ics23/go v0.7.0 h1:00d2kukk7sPoHWL4zZBZwzxnpA2pec1NPdwbSokJ5w8= +github.com/confio/ics23/go v0.7.0/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= @@ -629,8 +630,9 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/gin-gonic/gin v1.7.0 h1:jGB9xAJQ12AIGNB4HguylppmDK1Am9ppF7XnGXXJuoU= +github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-critic/go-critic v0.5.6/go.mod h1:cVjj0DfqewQVIlIAGexPCaGaZDAqGE29PYDDADIVNEo= @@ -756,7 +758,6 @@ github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2V github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -924,7 +925,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqC github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.0/go.mod h1:XnLCLFp3tjoZJszVKjfpyAK6J8sYIcQXWQxmqLWF21I= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= @@ -1661,15 +1661,16 @@ 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/flutter/v2 v2.0.3/go.mod h1:hnaVhWhzv2Od1LqZFWrRKwiOHeMonsB9EIWP0AGMPw0= -github.com/tendermint/fundraising v0.2.0 h1:V6N7u/oWXjQZEbXXk34uAfijYnYQFZrZGA39e03UFz8= github.com/tendermint/fundraising v0.2.0/go.mod h1:AoOF/njoU8FZMZTngspweCClg+3ANI0aRswe0FaUQsE= +github.com/tendermint/fundraising v0.3.0 h1:VtHfmVlAS93MUDlt6Em21l3taw6s9kLY/w8Cd1FB9fM= +github.com/tendermint/fundraising v0.3.0/go.mod h1:oJFZUZ/GsACtkYeWScKpHLdqMUThNWpMAi/G47LJUi4= 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/spm v0.1.8/go.mod h1:iHgfQ5YOI6ONc9E7ugGQolVdfSMHpeXfZ/OpXuN/42Q= github.com/tendermint/spn v0.1.1-0.20211210094128-4ca78a240c57/go.mod h1:p4BO8YC6kOKSKqMfySqaLHfwBmuPE/QcLwnnVhh7H9M= github.com/tendermint/spn v0.1.1-0.20220407154406-5cfd1bf28150/go.mod h1:B+KuhkB4Sms4yh0UN1HGsVbbMa3vCypai22QXLudQ3o= -github.com/tendermint/spn v0.2.1-0.20220427143342-de7398284030 h1:1S5urE/lHktsawx/I4r6iHiV1Ylfhp8mQZ5eQKbY1bA= -github.com/tendermint/spn v0.2.1-0.20220427143342-de7398284030/go.mod h1:9wXyogMDn9fK85s+bSADy+wvZ27DjLEByByMM+0O6NU= +github.com/tendermint/spn v0.2.1-0.20220511154430-aeab7a5b2bc0 h1:kIjnfHO472W2WSzul3ek3p07yKVYxSFUNng4YJmVex4= +github.com/tendermint/spn v0.2.1-0.20220511154430-aeab7a5b2bc0/go.mod h1:xNtBc/jmB1pvb+EJYQtyJdcTZM9dOhJeW3C4Qj9n7tg= github.com/tendermint/starport v0.19.5/go.mod h1:XdbMpJ5R6QzP1+yrfsoCk44fnp9/52raponbkvjIMQA= github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4= github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= @@ -2013,7 +2014,6 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2578,5 +2578,4 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= From fc17f36f9dae0be9102b23f7950c61867c215b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jer=C3=B3nimo=20Albi?= Date: Sat, 14 May 2022 20:35:16 +0200 Subject: [PATCH 5/8] fix: make sure proto package names are valid (#2480) The changes are based on the protocol buffers v3 language specification available at https://developers.google.com/protocol-buffers/docs/reference/proto3-spec#package --- ignite/templates/module/module.go | 10 ++++++++-- ignite/templates/module/module_test.go | 8 +++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ignite/templates/module/module.go b/ignite/templates/module/module.go index 6f34467088..bf543e5739 100644 --- a/ignite/templates/module/module.go +++ b/ignite/templates/module/module.go @@ -1,6 +1,7 @@ package module import ( + "regexp" "strings" "github.com/ignite-hq/cli/ignite/pkg/xstrings" @@ -14,7 +15,12 @@ func ProtoPackageName(appModulePath, moduleName string) string { // Make sure that the first path element can be used as proto package name. // This is required for app module names like "github.com/username/repo" where // "username" might be not be compatible with proto buffer package names. - path[0] = xstrings.FormatUsername(path[0]) + path[0] = xstrings.NoNumberPrefix(path[0]) - return strings.Join(path, ".") + return cleanProtoPackageName(strings.Join(path, ".")) +} + +func cleanProtoPackageName(name string) string { + r := regexp.MustCompile("[^a-zA-Z0-9_.]+") + return strings.ToLower(r.ReplaceAllString(name, "")) } diff --git a/ignite/templates/module/module_test.go b/ignite/templates/module/module_test.go index 2289cc0aed..1a29fc5afb 100644 --- a/ignite/templates/module/module_test.go +++ b/ignite/templates/module/module_test.go @@ -27,7 +27,7 @@ func TestProtoPackageName(t *testing.T) { }, { name: "path with dash", - app: "ignite-hq/cli", + app: "ignite-hq/c-li", module: "test", want: "ignitehq.cli.test", }, @@ -43,6 +43,12 @@ func TestProtoPackageName(t *testing.T) { module: "test", want: "_0ignitehq.cli.test", }, + { + name: "module with dash", + app: "ignite", + module: "test-mod", + want: "ignite.testmod", + }, } for _, tt := range cases { From fef912809ba7f66bc188f630a343c99dc744ca60 Mon Sep 17 00:00:00 2001 From: Tosin Omotoyinbo Date: Sun, 15 May 2022 11:57:56 +0100 Subject: [PATCH 6/8] feat: add authz module by default (#2455) * feat(modules): add authz to reservedNames * feat(modules): add authz imports to scaffold template * feat(modules): add authz module bindings * test(modules): add authz to expectedCosmosModules * fix(modules): rename declarations and resolve --- ignite/services/scaffolder/module.go | 1 + .../templates/app/stargate/app/app.go.plush | 63 ++++++++++++------- integration/cosmosgen/cosmosgen_test.go | 1 + 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/ignite/services/scaffolder/module.go b/ignite/services/scaffolder/module.go index b47f8f9ea6..1b1cff56d0 100644 --- a/ignite/services/scaffolder/module.go +++ b/ignite/services/scaffolder/module.go @@ -43,6 +43,7 @@ var ( reservedNames = map[string]struct{}{ "account": {}, "auth": {}, + "authz": {}, "bank": {}, "block": {}, "broadcast": {}, diff --git a/ignite/templates/app/stargate/app/app.go.plush b/ignite/templates/app/stargate/app/app.go.plush index b426de5f28..9b26480840 100644 --- a/ignite/templates/app/stargate/app/app.go.plush +++ b/ignite/templates/app/stargate/app/app.go.plush @@ -28,6 +28,9 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + "github.com/cosmos/cosmos-sdk/x/authz" + authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" + authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" "github.com/cosmos/cosmos-sdk/x/bank" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" @@ -76,8 +79,8 @@ import ( ibctransfertypes "github.com/cosmos/ibc-go/v2/modules/apps/transfer/types" ibc "github.com/cosmos/ibc-go/v2/modules/core" ibcclient "github.com/cosmos/ibc-go/v2/modules/core/02-client" - ibcclientclient "github.com/cosmos/ibc-go/v2/modules/core/02-client/client" - ibcclienttypes "github.com/cosmos/ibc-go/v2/modules/core/02-client/types" + ibcclientclient "github.com/cosmos/ibc-go/v2/modules/core/02-client/client" + ibcclienttypes "github.com/cosmos/ibc-go/v2/modules/core/02-client/types" ibcporttypes "github.com/cosmos/ibc-go/v2/modules/core/05-port/types" ibchost "github.com/cosmos/ibc-go/v2/modules/core/24-host" ibckeeper "github.com/cosmos/ibc-go/v2/modules/core/keeper" @@ -116,8 +119,8 @@ func getGovProposalHandlers() []govclient.ProposalHandler { distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler, - ibcclientclient.UpdateClientProposalHandler, - ibcclientclient.UpgradeProposalHandler, + ibcclientclient.UpdateClientProposalHandler, + ibcclientclient.UpgradeProposalHandler, // this line is used by starport scaffolding # stargate/app/govProposalHandler ) @@ -127,12 +130,13 @@ func getGovProposalHandlers() []govclient.ProposalHandler { var ( // DefaultNodeHome default home directories for the application daemon DefaultNodeHome string - + // ModuleBasics defines the module BasicManager is in charge of setting up basic, // non-dependant module elements, such as codec registration // and genesis verification. ModuleBasics = module.NewBasicManager( auth.AppModuleBasic{}, + authzmodule.AppModuleBasic{}, genutil.AppModuleBasic{}, bank.AppModuleBasic{}, capability.AppModuleBasic{}, @@ -200,6 +204,7 @@ type App struct { // keepers AccountKeeper authkeeper.AccountKeeper + AuthzKeeper authzkeeper.Keeper BankKeeper bankkeeper.Keeper CapabilityKeeper *capabilitykeeper.Keeper StakingKeeper stakingkeeper.Keeper @@ -217,8 +222,8 @@ type App struct { MonitoringKeeper monitoringpkeeper.Keeper // make scoped keepers public for test purposes - ScopedIBCKeeper capabilitykeeper.ScopedKeeper - ScopedTransferKeeper capabilitykeeper.ScopedKeeper + ScopedIBCKeeper capabilitykeeper.ScopedKeeper + ScopedTransferKeeper capabilitykeeper.ScopedKeeper ScopedMonitoringKeeper capabilitykeeper.ScopedKeeper // this line is used by starport scaffolding # stargate/app/keeperDeclaration @@ -253,7 +258,7 @@ func New( bApp.SetInterfaceRegistry(interfaceRegistry) keys := sdk.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, + authtypes.StoreKey, authz.ModuleName, banktypes.StoreKey, stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, capabilitytypes.StoreKey, monitoringptypes.StoreKey, @@ -290,6 +295,11 @@ func New( app.AccountKeeper = authkeeper.NewAccountKeeper( appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms, ) + + app.AuthzKeeper = authzkeeper.NewKeeper( + keys[authz.ModuleName], appCodec, app.MsgServiceRouter(), + ) + app.BankKeeper = bankkeeper.NewBaseKeeper( appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.ModuleAccountAddrs(), ) @@ -325,7 +335,7 @@ func New( // Create IBC Keeper app.IBCKeeper = ibckeeper.NewKeeper( appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper, - ) + ) // register the proposal types govRouter := govtypes.NewRouter() @@ -333,7 +343,7 @@ func New( AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)). AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)). AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). - AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) + AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) // Create Transfer Keepers app.TransferKeeper = ibctransferkeeper.NewKeeper( @@ -350,10 +360,10 @@ func New( // If evidence needs to be handled for the app, set routes in router here and seal app.EvidenceKeeper = *evidenceKeeper - app.GovKeeper = govkeeper.NewKeeper( - appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper, - &stakingKeeper, govRouter, - ) + app.GovKeeper = govkeeper.NewKeeper( + appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper, + &stakingKeeper, govRouter, + ) scopedMonitoringKeeper := app.CapabilityKeeper.ScopeToModule(monitoringptypes.ModuleName) app.MonitoringKeeper = *monitoringpkeeper.NewKeeper( @@ -372,12 +382,12 @@ func New( // this line is used by starport scaffolding # stargate/app/keeperDefinition - // Create static IBC router, add transfer route, then set and seal it + // Create static IBC router, add transfer route, then set and seal it ibcRouter := ibcporttypes.NewRouter() - ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule) + ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferModule) ibcRouter.AddRoute(monitoringptypes.ModuleName, monitoringModule) - // this line is used by starport scaffolding # ibc/app/router - app.IBCKeeper.SetRouter(ibcRouter) + // this line is used by starport scaffolding # ibc/app/router + app.IBCKeeper.SetRouter(ibcRouter) /**** Module Options ****/ @@ -394,6 +404,7 @@ func New( encodingConfig.TxConfig, ), auth.NewAppModule(appCodec, app.AccountKeeper, nil), + authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), vesting.NewAppModule(app.AccountKeeper, app.BankKeeper), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), capability.NewAppModule(appCodec, *app.CapabilityKeeper), @@ -429,6 +440,7 @@ func New( ibchost.ModuleName, ibctransfertypes.ModuleName, authtypes.ModuleName, + authz.ModuleName, banktypes.ModuleName, govtypes.ModuleName, crisistypes.ModuleName, @@ -445,6 +457,7 @@ func New( stakingtypes.ModuleName, capabilitytypes.ModuleName, authtypes.ModuleName, + authz.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, slashingtypes.ModuleName, @@ -469,6 +482,7 @@ func New( app.mm.SetOrderInitGenesis( capabilitytypes.ModuleName, authtypes.ModuleName, + authz.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, @@ -495,6 +509,7 @@ func New( // create the simulation manager and define the order of the modules for deterministic simulations app.sm = module.NewSimulationManager( auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), + authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), capability.NewAppModule(appCodec, *app.CapabilityKeeper), feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), @@ -573,7 +588,7 @@ func (app *App) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.Res if err := tmjson.Unmarshal(req.AppStateBytes, &genesisState); err != nil { panic(err) } - app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap()) + app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap()) return app.mm.InitGenesis(ctx, app.appCodec, genesisState) } @@ -652,15 +667,15 @@ func (app *App) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig // Register new tx routes from grpc-gateway. authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // Register new tendermint queries routes from grpc-gateway. - tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) + tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) // Register legacy and grpc-gateway routes for all modules. ModuleBasics.RegisterRESTRoutes(clientCtx, apiSvr.Router) ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter) - // register app's OpenAPI routes. - apiSvr.Router.Handle("/static/openapi.yml", http.FileServer(http.FS(docs.Docs))) - apiSvr.Router.HandleFunc("/", openapiconsole.Handler(Name, "/static/openapi.yml")) + // register app's OpenAPI routes. + apiSvr.Router.Handle("/static/openapi.yml", http.FileServer(http.FS(docs.Docs))) + apiSvr.Router.HandleFunc("/", openapiconsole.Handler(Name, "/static/openapi.yml")) } // RegisterTxService implements the Application.RegisterTxService method. @@ -695,7 +710,7 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govtypes.ParamKeyTable()) paramsKeeper.Subspace(crisistypes.ModuleName) paramsKeeper.Subspace(ibctransfertypes.ModuleName) - paramsKeeper.Subspace(ibchost.ModuleName) + paramsKeeper.Subspace(ibchost.ModuleName) paramsKeeper.Subspace(monitoringptypes.ModuleName) // this line is used by starport scaffolding # stargate/app/paramSubspace diff --git a/integration/cosmosgen/cosmosgen_test.go b/integration/cosmosgen/cosmosgen_test.go index 2ce286ace4..4f979728c8 100644 --- a/integration/cosmosgen/cosmosgen_test.go +++ b/integration/cosmosgen/cosmosgen_test.go @@ -116,6 +116,7 @@ func TestCosmosGen(t *testing.T) { var expectedCosmosModules = []string{ "cosmos.auth.v1beta1", + "cosmos.authz.v1beta1", "cosmos.bank.v1beta1", "cosmos.base.tendermint.v1beta1", "cosmos.crisis.v1beta1", From 5fdb44110c0e6daecb090f7ac38794b1fbd1fa80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jer=C3=B3nimo=20Albi?= Date: Mon, 16 May 2022 12:03:07 +0200 Subject: [PATCH 7/8] fix: shell completion generation when new version is available (#2484) The fix avoids invalid output to stdout when a new Ignite CLI version is available. --- ignite/cmd/cmd.go | 10 +++++++--- ignite/cmd/ignite/main.go | 2 +- ignite/internal/tools/gen-cli-docs/main.go | 3 +-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ignite/cmd/cmd.go b/ignite/cmd/cmd.go index 4069367659..d7fa86880b 100644 --- a/ignite/cmd/cmd.go +++ b/ignite/cmd/cmd.go @@ -35,11 +35,9 @@ const ( ) // New creates a new root command for `Ignite CLI` with its sub commands. -func New(ctx context.Context) *cobra.Command { +func New() *cobra.Command { cobra.EnableCommandSorting = false - checkNewVersion(ctx) - c := &cobra.Command{ Use: "ignite", Short: "Ignite CLI offers everything you need to scaffold, test, build, and launch your blockchain", @@ -53,6 +51,12 @@ ignite scaffold chain github.com/username/mars`, SilenceUsage: true, SilenceErrors: true, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + // Check for new versions only when shell completion scripts are not being + // generated to avoid invalid output to stdout when a new version is available + if cmd.Use != "completions" { + checkNewVersion(cmd.Context()) + } + return goenv.ConfigurePath() }, } diff --git a/ignite/cmd/ignite/main.go b/ignite/cmd/ignite/main.go index bf890d53cf..6202207857 100644 --- a/ignite/cmd/ignite/main.go +++ b/ignite/cmd/ignite/main.go @@ -14,7 +14,7 @@ import ( func main() { ctx := clictx.From(context.Background()) - err := ignitecmd.New(ctx).ExecuteContext(ctx) + err := ignitecmd.New().ExecuteContext(ctx) if ctx.Err() == context.Canceled || err == context.Canceled { fmt.Println("aborted") diff --git a/ignite/internal/tools/gen-cli-docs/main.go b/ignite/internal/tools/gen-cli-docs/main.go index cbcd932318..5ec83ed3aa 100644 --- a/ignite/internal/tools/gen-cli-docs/main.go +++ b/ignite/internal/tools/gen-cli-docs/main.go @@ -5,7 +5,6 @@ package main import ( "bufio" "bytes" - "context" "flag" "fmt" "io" @@ -37,7 +36,7 @@ func main() { outPath := flag.String("out", ".", ".md file path to place Ignite CLI docs inside") flag.Parse() - if err := generate(ignitecmd.New(context.Background()), *outPath); err != nil { + if err := generate(ignitecmd.New(), *outPath); err != nil { log.Fatal(err) } } From db7499071cea81a3f282f70956c09a0828526de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=2E=20=C3=96zt=C3=BCrk?= Date: Mon, 16 May 2022 13:29:37 +0300 Subject: [PATCH 8/8] feat: make sure to support chains built w/ SDK '>= v0.46.0-alpha1' (#2485) --- changelog.md | 12 ++++++++++++ ignite/services/chain/plugin-stargate.go | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/changelog.md b/changelog.md index 8ce53d4597..f80b615084 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,17 @@ # Changelog +## [`v0.21.1`](https://github.com/ignite-hq/cli/releases/tag/v0.21.1) + +### Features + +- Add compatibility to run chains built with Cosmos-SDK `v0.46.0-alpha1` and above +- Scaffold chains now will have `auth` module enabled by default + +### Fixes + +- Fixed shell completion generation +- Make sure proto package names are valid when using simple app names + ## [`v0.21.0`](https://github.com/ignite-hq/cli/releases/tag/v0.21.0) ### Features diff --git a/ignite/services/chain/plugin-stargate.go b/ignite/services/chain/plugin-stargate.go index a66d2d73a7..a0ed00f563 100644 --- a/ignite/services/chain/plugin-stargate.go +++ b/ignite/services/chain/plugin-stargate.go @@ -8,6 +8,7 @@ import ( "github.com/pelletier/go-toml" + sdktypes "github.com/cosmos/cosmos-sdk/types" "github.com/ignite-hq/cli/ignite/chainconfig" "github.com/ignite-hq/cli/ignite/pkg/chaincmd" chaincmdrunner "github.com/ignite-hq/cli/ignite/pkg/chaincmd/runner" @@ -77,6 +78,13 @@ func (p *stargatePlugin) appTOML(homePath string, conf chainconfig.Config) error config.Set("grpc.address", conf.Host.GRPC) config.Set("grpc-web.address", conf.Host.GRPCWeb) + staked, err := sdktypes.ParseCoinNormalized(conf.Validator.Staked) + if err != nil { + return err + } + gas := sdktypes.NewInt64Coin(staked.Denom, 80000) + config.Set("minimum-gas-prices", gas.String()) + file, err := os.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0644) if err != nil { return err @@ -105,6 +113,7 @@ func (p *stargatePlugin) configTOML(homePath string, conf chainconfig.Config) er return fmt.Errorf("invalid p2p address format %s: %w", conf.Host.P2P, err) } + config.Set("mode", "validator") config.Set("rpc.cors_allowed_origins", []string{"*"}) config.Set("consensus.timeout_commit", "1s") config.Set("consensus.timeout_propose", "1s")