diff --git a/chain/cosmos/chain_node.go b/chain/cosmos/chain_node.go index 16e21afee..f80724d1a 100644 --- a/chain/cosmos/chain_node.go +++ b/chain/cosmos/chain_node.go @@ -1039,6 +1039,30 @@ func (tn *ChainNode) QueryClientContractCode(ctx context.Context, codeHash strin return err } +// GetModuleAddress performs a query to get the address of the specified chain module +func (tn *ChainNode) GetModuleAddress(ctx context.Context, moduleName string) (string, error) { + queryRes, err := tn.GetModuleAccount(ctx, moduleName) + if err != nil { + return "", err + } + return queryRes.Account.BaseAccount.Address, nil +} + +// GetModuleAccount performs a query to get the account details of the specified chain module +func (tn *ChainNode) GetModuleAccount(ctx context.Context, moduleName string) (QueryModuleAccountResponse, error) { + stdout, _, err := tn.ExecQuery(ctx, "auth", "module-account", moduleName) + if err != nil { + return QueryModuleAccountResponse{}, err + } + + queryRes := QueryModuleAccountResponse{} + err = json.Unmarshal(stdout, &queryRes) + if err != nil { + return QueryModuleAccountResponse{}, err + } + return queryRes, nil +} + // VoteOnProposal submits a vote for the specified proposal. func (tn *ChainNode) VoteOnProposal(ctx context.Context, keyName string, proposalID string, vote string) error { _, err := tn.ExecTx(ctx, keyName, diff --git a/chain/cosmos/cosmos_chain.go b/chain/cosmos/cosmos_chain.go index 7db8d9d09..795580e22 100644 --- a/chain/cosmos/cosmos_chain.go +++ b/chain/cosmos/cosmos_chain.go @@ -374,6 +374,16 @@ func (c *CosmosChain) SendIBCTransfer( return tx, nil } +// GetGovernanceAddress performs a query to get the address of the chain's x/gov module +func (c *CosmosChain) GetGovernanceAddress(ctx context.Context) (string, error) { + return c.GetModuleAddress(ctx, govtypes.ModuleName) +} + +// GetModuleAddress performs a query to get the address of the specified chain module +func (c *CosmosChain) GetModuleAddress(ctx context.Context, moduleName string) (string, error) { + return c.getFullNode().GetModuleAddress(ctx, moduleName) +} + // QueryProposal returns the state and details of a governance proposal. func (c *CosmosChain) QueryProposal(ctx context.Context, proposalID string) (*ProposalResponse, error) { return c.getFullNode().QueryProposal(ctx, proposalID) diff --git a/chain/cosmos/types.go b/chain/cosmos/types.go index 2104d3d1f..71666b5ac 100644 --- a/chain/cosmos/types.go +++ b/chain/cosmos/types.go @@ -153,3 +153,15 @@ type DenomAuthorityMetadata struct { // Can be empty for no admin, or a valid address Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty" yaml:"admin"` } + +type QueryModuleAccountResponse struct { + Account struct { + BaseAccount struct { + AccountNumber string `json:"account_number"` + Address string `json:"address"` + PubKey string `json:"pub_key"` + Sequence string `json:"sequence"` + } `json:"base_account"` + Name string `json:"name"` + } `json:"account"` +} diff --git a/examples/cosmos/chain_miscellaneous_test.go b/examples/cosmos/chain_miscellaneous_test.go index c29bbc0a8..d2433e678 100644 --- a/examples/cosmos/chain_miscellaneous_test.go +++ b/examples/cosmos/chain_miscellaneous_test.go @@ -88,6 +88,7 @@ func CosmosChainTestMiscellaneous(t *testing.T, name, version string) { testHasCommand(ctx, t, chain) testTokenFactory(ctx, t, chain, users) testAddingNode(ctx, t, chain) + testGetGovernanceAddress(ctx, t, chain) } func testBuildDependencies(ctx context.Context, t *testing.T, chain *cosmos.CosmosChain) { @@ -376,6 +377,13 @@ func testTokenFactory(ctx context.Context, t *testing.T, chain *cosmos.CosmosCha } +func testGetGovernanceAddress(ctx context.Context, t *testing.T, chain *cosmos.CosmosChain) { + govAddr, err := chain.GetGovernanceAddress(ctx) + require.NoError(t, err) + _, err = sdk.AccAddressFromBech32(govAddr) + require.NoError(t, err) +} + // helpers func sendTokens(ctx context.Context, chain *cosmos.CosmosChain, from, to ibc.Wallet, token string, amount int64) (ibc.WalletAmount, error) { if token == "" {