diff --git a/Makefile b/Makefile index 1c5584a32..da5406ee1 100644 --- a/Makefile +++ b/Makefile @@ -13,8 +13,8 @@ all: lint build test-unit ### Build flags ### ############################################################################### -LD_FLAGS = -X github.com/desmos-labs/juno/version.Version=$(VERSION) \ - -X github.com/desmos-labs/juno/version.Commit=$(COMMIT) +LD_FLAGS = -X github.com/forbole/juno/version.Version=$(VERSION) \ + -X github.com/forbole/juno/version.Commit=$(COMMIT) BUILD_FLAGS := -ldflags '$(LD_FLAGS)' diff --git a/README.md b/README.md index 62114fa60..f74fd6193 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/forbole/bdjuno)](https://goreportcard.com/report/github.com/forbole/bdjuno) ![Codecov branch](https://img.shields.io/codecov/c/github/forbole/bdjuno/cosmos/v0.40.x) -BDJuno (shorthand for BigDipper Juno) is the [Juno](https://github.com/desmos-labs/juno) implementation +BDJuno (shorthand for BigDipper Juno) is the [Juno](https://github.com/forbole/juno) implementation for [BigDipper](https://github.com/forbole/big-dipper). It extends the custom Juno behavior by adding different handlers and custom operations to make it easier for BigDipper diff --git a/cmd/bdjuno/main.go b/cmd/bdjuno/main.go index f4a9799b9..501848c32 100644 --- a/cmd/bdjuno/main.go +++ b/cmd/bdjuno/main.go @@ -8,6 +8,7 @@ import ( parsecmd "github.com/forbole/juno/v2/cmd/parse" "github.com/forbole/juno/v2/modules/messages" + fixcmd "github.com/forbole/bdjuno/v2/cmd/fix" migratecmd "github.com/forbole/bdjuno/v2/cmd/migrate" "github.com/forbole/bdjuno/v2/types/config" @@ -32,7 +33,8 @@ func main() { cmd.VersionCmd(), initcmd.InitCmd(cfg.GetInitConfig()), parsecmd.ParseCmd(cfg.GetParseConfig()), - migratecmd.MigrateCmd(), + migratecmd.NewMigrateCmd(), + fixcmd.NewFixCmd(cfg.GetParseConfig()), ) executor := cmd.PrepareRootCmd(cfg.GetName(), rootCmd) diff --git a/cmd/fix/fix.go b/cmd/fix/fix.go new file mode 100644 index 000000000..fdf808966 --- /dev/null +++ b/cmd/fix/fix.go @@ -0,0 +1,40 @@ +package fix + +import ( + "github.com/forbole/juno/v2/cmd/parse" + "github.com/spf13/cobra" + + fixgov "github.com/forbole/bdjuno/v2/cmd/fix/gov" + fixstaking "github.com/forbole/bdjuno/v2/cmd/fix/staking" +) + +// NewFixCmd returns the Cobra command allowing to fix some BDJuno bugs without having to re-sync the whole database +func NewFixCmd(parseCfg *parse.Config) *cobra.Command { + cmd := &cobra.Command{ + Use: "fix", + Short: "Apply some fixes without the need to re-syncing the whole database from scratch", + PersistentPreRunE: runPersistentPreRuns(parse.ReadConfig(parseCfg)), + } + + cmd.AddCommand( + fixgov.NewGovCmd(parseCfg), + fixstaking.NewStakingCmd(parseCfg), + ) + + return cmd +} + +func runPersistentPreRuns(preRun func(_ *cobra.Command, _ []string) error) func(_ *cobra.Command, _ []string) error { + return func(cmd *cobra.Command, args []string) error { + if root := cmd.Root(); root != nil { + if root.PersistentPreRunE != nil { + err := root.PersistentPreRunE(root, args) + if err != nil { + return err + } + } + } + + return preRun(cmd, args) + } +} diff --git a/cmd/fix/gov/cmd.go b/cmd/fix/gov/cmd.go new file mode 100644 index 000000000..d0ed44a2c --- /dev/null +++ b/cmd/fix/gov/cmd.go @@ -0,0 +1,20 @@ +package gov + +import ( + "github.com/forbole/juno/v2/cmd/parse" + "github.com/spf13/cobra" +) + +// NewGovCmd returns the Cobra command allowing to fix various things related to the x/gov module +func NewGovCmd(parseConfig *parse.Config) *cobra.Command { + cmd := &cobra.Command{ + Use: "gov", + Short: "Fix things related to the x/gov module", + } + + cmd.AddCommand( + proposalCmd(parseConfig), + ) + + return cmd +} diff --git a/cmd/fix/gov/proposal.go b/cmd/fix/gov/proposal.go new file mode 100644 index 000000000..1a4f6bf66 --- /dev/null +++ b/cmd/fix/gov/proposal.go @@ -0,0 +1,152 @@ +package gov + +import ( + "encoding/hex" + "fmt" + + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/forbole/juno/v2/cmd/parse" + "github.com/forbole/juno/v2/types/config" + "github.com/spf13/cobra" + + "github.com/forbole/bdjuno/v2/database" + "github.com/forbole/bdjuno/v2/modules" + "github.com/forbole/bdjuno/v2/modules/gov" + "github.com/forbole/bdjuno/v2/utils" +) + +// proposalCmd returns the Cobra command allowing to fix all things related to a proposal +func proposalCmd(parseConfig *parse.Config) *cobra.Command { + return &cobra.Command{ + Use: "proposal [id]", + Short: "Get the description, votes and everything related to a proposal given its id", + RunE: func(cmd *cobra.Command, args []string) error { + proposalID := args[0] + + parseCtx, err := parse.GetParsingContext(parseConfig) + if err != nil { + return err + } + + sources, err := modules.BuildSources(config.Cfg.Node, parseCtx.EncodingConfig) + if err != nil { + return err + } + + // Get the database + db := database.Cast(parseCtx.Database) + + // Build the gov module + govModule := gov.NewModule(parseCtx.EncodingConfig.Marshaler, sources.GovSource, nil, nil, nil, db) + + err = refreshProposalDetails(parseCtx, proposalID, govModule) + if err != nil { + return err + } + + err = refreshProposalDeposits(parseCtx, proposalID, govModule) + if err != nil { + return err + } + + err = refreshProposalVotes(parseCtx, proposalID, govModule) + if err != nil { + return err + } + + return nil + }, + } +} + +func refreshProposalDetails(parseCtx *parse.Context, proposalID string, govModule *gov.Module) error { + // Get the tx that created the proposal + txs, err := utils.QueryTxs(parseCtx.Node, fmt.Sprintf("submit_proposal.proposal_id=%s", proposalID)) + if err != nil { + return err + } + + if len(txs) > 1 { + return fmt.Errorf("expecting only one create proposal transaction, found %d", len(txs)) + } + + // Get the tx details + tx, err := parseCtx.Node.Tx(hex.EncodeToString(txs[0].Tx.Hash())) + if err != nil { + return err + } + + // Handle the MsgSubmitProposal messages + for index, msg := range tx.GetMsgs() { + if _, ok := msg.(*govtypes.MsgSubmitProposal); !ok { + continue + } + + err = govModule.HandleMsg(index, msg, tx) + if err != nil { + return fmt.Errorf("error while handling MsgSubmitProposal: %s", err) + } + } + + return nil +} + +func refreshProposalDeposits(parseCtx *parse.Context, proposalID string, govModule *gov.Module) error { + // Get the tx that deposited to the proposal + txs, err := utils.QueryTxs(parseCtx.Node, fmt.Sprintf("proposal_deposit.proposal_id=%s", proposalID)) + if err != nil { + return err + } + + for _, tx := range txs { + // Get the tx details + junoTx, err := parseCtx.Node.Tx(hex.EncodeToString(tx.Tx.Hash())) + if err != nil { + return err + } + + // Handle the MsgDeposit messages + for index, msg := range junoTx.GetMsgs() { + if _, ok := msg.(*govtypes.MsgDeposit); !ok { + continue + } + + err = govModule.HandleMsg(index, msg, junoTx) + if err != nil { + return fmt.Errorf("error while handling MsgDeposit: %s", err) + } + } + } + + return nil +} + +func refreshProposalVotes(parseCtx *parse.Context, proposalID string, govModule *gov.Module) error { + // Get the tx that voted the proposal + txs, err := utils.QueryTxs(parseCtx.Node, fmt.Sprintf("proposal_vote.proposal_id=%s", proposalID)) + if err != nil { + return err + } + + for _, tx := range txs { + // Get the tx details + junoTx, err := parseCtx.Node.Tx(hex.EncodeToString(tx.Tx.Hash())) + if err != nil { + return err + } + + // Handle the MsgVote messages + for index, msg := range junoTx.GetMsgs() { + if _, ok := msg.(*govtypes.MsgVote); !ok { + continue + } + + err = govModule.HandleMsg(index, msg, junoTx) + if err != nil { + return fmt.Errorf("error while handling MsgVote: %s", err) + } + } + } + + return nil +} diff --git a/cmd/fix/staking/cmd.go b/cmd/fix/staking/cmd.go new file mode 100644 index 000000000..55612aca4 --- /dev/null +++ b/cmd/fix/staking/cmd.go @@ -0,0 +1,21 @@ +package staking + +import ( + "github.com/forbole/juno/v2/cmd/parse" + "github.com/spf13/cobra" +) + +// NewStakingCmd returns the Cobra command that allows to fix all the things related to the x/staking module +func NewStakingCmd(parseConfig *parse.Config) *cobra.Command { + cmd := &cobra.Command{ + Use: "staking", + Short: "Fix things related to the x/staking module", + } + + cmd.AddCommand( + validatorsCmd(parseConfig), + slashesCmd(parseConfig), + ) + + return cmd +} diff --git a/cmd/fix/staking/slashes.go b/cmd/fix/staking/slashes.go new file mode 100644 index 000000000..f03361dd5 --- /dev/null +++ b/cmd/fix/staking/slashes.go @@ -0,0 +1,69 @@ +package staking + +import ( + "fmt" + + "github.com/forbole/juno/v2/cmd/parse" + "github.com/forbole/juno/v2/types/config" + "github.com/spf13/cobra" + + "github.com/forbole/bdjuno/v2/database" + "github.com/forbole/bdjuno/v2/modules" + "github.com/forbole/bdjuno/v2/modules/staking" +) + +// slashesCmd returns a Cobra command that allows to fix the delegations for all the slashed validators. +func slashesCmd(parseConfig *parse.Config) *cobra.Command { + return &cobra.Command{ + Use: "slashes", + Short: "Fix the delegations for all the slashed validators, taking their delegations from the latest known height", + RunE: func(cmd *cobra.Command, args []string) error { + parseCtx, err := parse.GetParsingContext(parseConfig) + if err != nil { + return err + } + + sources, err := modules.BuildSources(config.Cfg.Node, parseCtx.EncodingConfig) + if err != nil { + return err + } + + // Get the database + db := database.Cast(parseCtx.Database) + + // Get latest height + height, err := parseCtx.Node.LatestHeight() + if err != nil { + return fmt.Errorf("error while getting latest block height: %s", err) + } + + // Get all validators + validators, err := sources.StakingSource.GetValidatorsWithStatus(height, "") + if err != nil { + return fmt.Errorf("error while getting validators: %s", err) + } + + for _, validator := range validators { + // Get the validator delegations + delegations, err := sources.StakingSource.GetValidatorDelegations(height, validator.OperatorAddress) + if err != nil { + return fmt.Errorf("error while getting validator delegations: %s", err) + } + + // Delete the old delegations + err = db.DeleteValidatorDelegations(validator.OperatorAddress) + if err != nil { + return fmt.Errorf("error while deleting validator delegations: %s", err) + } + + // Save the delegations + err = db.SaveDelegations(staking.ConvertDelegationsResponses(height, delegations)) + if err != nil { + return fmt.Errorf("error while saving delegations: %s", err) + } + } + + return nil + }, + } +} diff --git a/cmd/fix/staking/validators.go b/cmd/fix/staking/validators.go new file mode 100644 index 000000000..3d93caf6b --- /dev/null +++ b/cmd/fix/staking/validators.go @@ -0,0 +1,60 @@ +package staking + +import ( + "fmt" + + "github.com/forbole/juno/v2/cmd/parse" + "github.com/forbole/juno/v2/types/config" + "github.com/spf13/cobra" + + "github.com/forbole/bdjuno/v2/database" + "github.com/forbole/bdjuno/v2/modules" + "github.com/forbole/bdjuno/v2/modules/staking" +) + +// validatorsCmd returns a Cobra command that allows to fix the validator infos for all validators. +func validatorsCmd(parseConfig *parse.Config) *cobra.Command { + return &cobra.Command{ + Use: "validators", + Short: "Fix the information about validators taking them from the latest known height", + RunE: func(cmd *cobra.Command, args []string) error { + parseCtx, err := parse.GetParsingContext(parseConfig) + if err != nil { + return err + } + + sources, err := modules.BuildSources(config.Cfg.Node, parseCtx.EncodingConfig) + if err != nil { + return err + } + + // Get the database + db := database.Cast(parseCtx.Database) + + // Build the staking module + stakingModule := staking.NewModule(sources.StakingSource, nil, nil, nil, parseCtx.EncodingConfig.Marshaler, db) + + // Get latest height + height, err := parseCtx.Node.LatestHeight() + if err != nil { + return fmt.Errorf("error while getting latest block height: %s", err) + } + + // Get all validators + validators, err := sources.StakingSource.GetValidatorsWithStatus(height, "") + if err != nil { + return fmt.Errorf("error while getting validators: %s", err) + } + + // Refresh each validator + for _, validator := range validators { + err = stakingModule.RefreshValidatorInfos(height, validator.OperatorAddress) + if err != nil { + return fmt.Errorf("error while refreshing validator: %s", err) + } + } + + return nil + }, + } +} diff --git a/cmd/migrate/migrate.go b/cmd/migrate/migrate.go index cd124e047..b38227f8d 100644 --- a/cmd/migrate/migrate.go +++ b/cmd/migrate/migrate.go @@ -23,9 +23,8 @@ type Config struct { DistributionConfig *distribution.Config `yaml:"distribution"` } -// MigrateCmd returns the command to be run when migrating the config from v1 to v2 -// nolint: golint -func MigrateCmd() *cobra.Command { +// NewMigrateCmd returns the command to be run when migrating the config from v1 to v2 +func NewMigrateCmd() *cobra.Command { return &cobra.Command{ Use: "migrate", RunE: func(cmd *cobra.Command, args []string) error { diff --git a/database/gov.go b/database/gov.go index f7f298019..f86a28c62 100644 --- a/database/gov.go +++ b/database/gov.go @@ -96,15 +96,22 @@ func (db *Db) SaveProposals(proposals []types.Proposal) error { return nil } - query := ` + var accounts []types.Account + + proposalsQuery := ` INSERT INTO proposal( id, title, description, content, proposer_address, proposal_route, proposal_type, status, submit_time, deposit_end_time, voting_start_time, voting_end_time ) VALUES` - var param []interface{} + var proposalsParams []interface{} + for i, proposal := range proposals { + // Prepare the account query + accounts = append(accounts, types.NewAccount(proposal.Proposer)) + + // Prepare the proposal query vi := i * 12 - query += fmt.Sprintf("($%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d),", + proposalsQuery += fmt.Sprintf("($%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d,$%d),", vi+1, vi+2, vi+3, vi+4, vi+5, vi+6, vi+7, vi+8, vi+9, vi+10, vi+11, vi+12) // Encode the content properly @@ -123,7 +130,7 @@ INSERT INTO proposal( return fmt.Errorf("error while marshaling proposal content: %s", err) } - param = append(param, + proposalsParams = append(proposalsParams, proposal.ProposalID, proposal.Content.GetTitle(), proposal.Content.GetDescription(), @@ -138,11 +145,19 @@ INSERT INTO proposal( proposal.VotingEndTime, ) } - query = query[:len(query)-1] // Remove trailing "," - query += " ON CONFLICT DO NOTHING" - _, err := db.Sql.Exec(query, param...) + + // Store the accounts + err := db.SaveAccounts(accounts) if err != nil { - return fmt.Errorf("error while storing proposal: %s", err) + return fmt.Errorf("error while storing proposers accounts: %s", err) + } + + // Store the proposals + proposalsQuery = proposalsQuery[:len(proposalsQuery)-1] // Remove trailing "," + proposalsQuery += " ON CONFLICT DO NOTHING" + _, err = db.Sql.Exec(proposalsQuery, proposalsParams...) + if err != nil { + return fmt.Errorf("error while storing proposals: %s", err) } return nil @@ -259,12 +274,13 @@ ON CONFLICT ON CONSTRAINT unique_vote DO UPDATE height = excluded.height WHERE proposal_vote.height <= excluded.height` - _, err := db.Sql.Exec(query, - vote.ProposalID, - vote.Voter, - vote.Option.String(), - vote.Height, - ) + // Store the voter account + err := db.SaveAccounts([]types.Account{types.NewAccount(vote.Voter)}) + if err != nil { + return fmt.Errorf("error while storing voter account: %s", err) + } + + _, err = db.Sql.Exec(query, vote.ProposalID, vote.Voter, vote.Option.String(), vote.Height) if err != nil { return fmt.Errorf("error while storing vote: %s", err) } diff --git a/go.mod b/go.mod index 0b924d6c0..1e2e9ab27 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/cosmos/cosmos-sdk v0.42.9 - github.com/forbole/juno/v2 v2.0.0-20211018063058-c8a1eb5d5312 + github.com/forbole/juno/v2 v2.0.0-20211018083707-de5b5378416e github.com/go-co-op/gocron v0.3.3 github.com/gogo/protobuf v1.3.3 github.com/jmoiron/sqlx v1.2.1-0.20200324155115-ee514944af4b diff --git a/go.sum b/go.sum index df03db72a..bf828cc0e 100644 --- a/go.sum +++ b/go.sum @@ -186,8 +186,8 @@ github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+ne github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/forbole/juno/v2 v2.0.0-20211018063058-c8a1eb5d5312 h1:trppuVzd+WfS4Y9EWt4THynTExj3XpETElOJEHqOKDA= -github.com/forbole/juno/v2 v2.0.0-20211018063058-c8a1eb5d5312/go.mod h1:nOZEHr5+sZDXEDpV2E+NHkmH0Zvf4prkt5+UVKwScQ8= +github.com/forbole/juno/v2 v2.0.0-20211018083707-de5b5378416e h1:TNfbPyOvqJG9BC2EzpsPhtmeb4SaQl1f5SLHytiFVKQ= +github.com/forbole/juno/v2 v2.0.0-20211018083707-de5b5378416e/go.mod h1:nOZEHr5+sZDXEDpV2E+NHkmH0Zvf4prkt5+UVKwScQ8= github.com/forbole/tendermint v0.34.13-0.20210820072129-a2a4af55563d h1:pUqGUgTUU24ibHeloQeg1F2pFbgQllddsuZ+x+CcUzw= github.com/forbole/tendermint v0.34.13-0.20210820072129-a2a4af55563d/go.mod h1:aeHL7alPh4uTBIJQ8mgFEE8VwJLXI1VD3rVOmH2Mcy0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= diff --git a/modules/registrar.go b/modules/registrar.go index ea8227ac9..1b038de55 100644 --- a/modules/registrar.go +++ b/modules/registrar.go @@ -100,7 +100,7 @@ func (r *Registrar) BuildModules(ctx registrar.Context) jmodules.Modules { cdc := ctx.EncodingConfig.Marshaler db := database.Cast(ctx.Database) - sources, err := buildSources(ctx.JunoConfig.Node, ctx.EncodingConfig) + sources, err := BuildSources(ctx.JunoConfig.Node, ctx.EncodingConfig) if err != nil { panic(err) } @@ -139,7 +139,7 @@ type Sources struct { StakingSource stakingsource.Source } -func buildSources(nodeCfg nodeconfig.Config, encodingConfig *params.EncodingConfig) (*Sources, error) { +func BuildSources(nodeCfg nodeconfig.Config, encodingConfig *params.EncodingConfig) (*Sources, error) { switch cfg := nodeCfg.Details.(type) { case *remote.Details: return buildRemoteSources(cfg) diff --git a/modules/staking/handle_msg.go b/modules/staking/handle_msg.go index d46caf049..46e27da2a 100644 --- a/modules/staking/handle_msg.go +++ b/modules/staking/handle_msg.go @@ -40,7 +40,7 @@ func (m *Module) HandleMsg(index int, msg sdk.Msg, tx *juno.Tx) error { // handleMsgCreateValidator handles properly a MsgCreateValidator instance by // saving into the database all the data associated to such validator func (m *Module) handleMsgCreateValidator(height int64, msg *stakingtypes.MsgCreateValidator) error { - err := m.refreshValidatorInfos(height, msg.ValidatorAddress) + err := m.RefreshValidatorInfos(height, msg.ValidatorAddress) if err != nil { return fmt.Errorf("error while refreshing validator from MsgCreateValidator: %s", err) } @@ -56,7 +56,7 @@ func (m *Module) handleMsgCreateValidator(height int64, msg *stakingtypes.MsgCre // handleEditValidator handles MsgEditValidator utils, updating the validator info and commission func (m *Module) handleEditValidator(height int64, msg *stakingtypes.MsgEditValidator) error { - err := m.refreshValidatorInfos(height, msg.ValidatorAddress) + err := m.RefreshValidatorInfos(height, msg.ValidatorAddress) if err != nil { return fmt.Errorf("error while refreshing validator from MsgEditValidator: %s", err) } diff --git a/modules/staking/utils_delegations.go b/modules/staking/utils_delegations.go index 5d61e006f..48414f69f 100644 --- a/modules/staking/utils_delegations.go +++ b/modules/staking/utils_delegations.go @@ -24,8 +24,8 @@ func convertDelegationResponse(height int64, response stakingtypes.DelegationRes ) } -// convertDelegationsResponses converts the given responses to BDJuno Delegation instances -func convertDelegationsResponses(height int64, responses []stakingtypes.DelegationResponse) []types.Delegation { +// ConvertDelegationsResponses converts the given responses to BDJuno Delegation instances +func ConvertDelegationsResponses(height int64, responses []stakingtypes.DelegationResponse) []types.Delegation { var delegations = make([]types.Delegation, len(responses)) for index, delegation := range responses { delegations[index] = convertDelegationResponse(height, delegation) @@ -42,7 +42,7 @@ func (m *Module) getValidatorDelegations(height int64, validator string) ([]type return nil, fmt.Errorf("error while getting validator delegations: %s", err) } - return convertDelegationsResponses(height, delegations), nil + return ConvertDelegationsResponses(height, delegations), nil } // getDelegatorDelegations returns the current delegations for the given delegator @@ -52,7 +52,7 @@ func (m *Module) getDelegatorDelegations(height int64, delegator string) ([]type return nil, fmt.Errorf("error while getting delegator delegations: %s", err) } - return convertDelegationsResponses(height, responses), nil + return ConvertDelegationsResponses(height, responses), nil } // -------------------------------------------------------------------------------------------------------------------- @@ -69,7 +69,7 @@ func (m *Module) RefreshValidatorDelegations(height int64, valOperAddr string) e return fmt.Errorf("error while deleting validator delegations: %s", err) } - err = m.db.SaveDelegations(convertDelegationsResponses(height, responses)) + err = m.db.SaveDelegations(ConvertDelegationsResponses(height, responses)) if err != nil { return fmt.Errorf("error while storing validator delegations: %s", err) } diff --git a/modules/staking/utils_validators.go b/modules/staking/utils_validators.go index 4e000baea..501c530a7 100644 --- a/modules/staking/utils_validators.go +++ b/modules/staking/utils_validators.go @@ -80,8 +80,8 @@ func (m *Module) convertValidatorDescription( // -------------------------------------------------------------------------------------------------------------------- -// refreshValidatorInfos refreshes the info for the validator with the given operator address at the provided height -func (m *Module) refreshValidatorInfos(height int64, valOper string) error { +// RefreshValidatorInfos refreshes the info for the validator with the given operator address at the provided height +func (m *Module) RefreshValidatorInfos(height int64, valOper string) error { stakingValidator, err := m.source.GetValidator(height, valOper) if err != nil { return err diff --git a/utils/node.go b/utils/node.go new file mode 100644 index 000000000..e621cdaaa --- /dev/null +++ b/utils/node.go @@ -0,0 +1,29 @@ +package utils + +import ( + "fmt" + + "github.com/forbole/juno/v2/node" + coretypes "github.com/tendermint/tendermint/rpc/core/types" +) + +// QueryTxs queries all the transactions from the given node corresponding to the given query +func QueryTxs(node node.Node, query string) ([]*coretypes.ResultTx, error) { + var txs []*coretypes.ResultTx + + var page = 1 + var perPage = 100 + var stop = false + for !stop { + result, err := node.TxSearch(query, &page, &perPage, "") + if err != nil { + return nil, fmt.Errorf("error while running tx search: %s", err) + } + + page++ + txs = append(txs, result.Txs...) + stop = len(txs) == result.TotalCount + } + + return txs, nil +}