Skip to content

Commit

Permalink
feat: init
Browse files Browse the repository at this point in the history
  • Loading branch information
freak12techno committed Jun 7, 2022
0 parents commit 1cb76ed
Show file tree
Hide file tree
Showing 11 changed files with 610 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
config.toml
main
*.json
71 changes: 71 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package main

import (
"fmt"
"os"

"github.com/BurntSushi/toml"
)

type Chain struct {
Name string `toml:"name"`
LCDEndpoints []string `toml:"lcd-endpoints"`
Wallets []string `toml:"wallets"`
}

func (c *Chain) Validate() error {
if c.Name == "" {
return fmt.Errorf("empty chain name")
}

if len(c.LCDEndpoints) == 0 {
return fmt.Errorf("no LCD endpoints provided")
}

if len(c.Wallets) == 0 {
return fmt.Errorf("no wallets provided")
}

return nil
}

type Config struct {
LogConfig LogConfig `toml:"log"`
StatePath string `toml:"state-path"`
Chains []Chain `toml:"chains"`
}

type LogConfig struct {
LogLevel string `toml:"level"`
JSONOutput bool `toml:"json"`
}

func (c *Config) Validate() error {
if len(c.Chains) == 0 {
return fmt.Errorf("no chains provided")
}

for index, chain := range c.Chains {
if err := chain.Validate(); err != nil {
return fmt.Errorf("error in chain %d: %s", index, err)
}
}

return nil
}

func GetConfig(path string) (*Config, error) {
configBytes, err := os.ReadFile(path)
if err != nil {
return nil, err
}

configString := string(configBytes)

configStruct := Config{}
if _, err = toml.Decode(configString, &configStruct); err != nil {
return nil, err
}

return &configStruct, nil
}
14 changes: 14 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module main

go 1.18

require (
github.com/BurntSushi/toml v1.1.0
github.com/rs/zerolog v1.26.1
github.com/spf13/cobra v1.4.0
)

require (
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
44 changes: 44 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc=
github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
28 changes: 28 additions & 0 deletions logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package main

import (
"os"

"github.com/rs/zerolog"
)

func GetDefaultLogger() *zerolog.Logger {
log := zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout}).With().Timestamp().Logger()
return &log
}

func GetLogger(config LogConfig) *zerolog.Logger {
log := zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout}).With().Timestamp().Logger()

logLevel, err := zerolog.ParseLevel(config.LogLevel)
if err != nil {
log.Fatal().Err(err).Msg("Could not parse log level")
}

if config.JSONOutput {
log = zerolog.New(os.Stdout).With().Timestamp().Logger()
}

zerolog.SetGlobalLevel(logLevel)
return &log
}
52 changes: 52 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package main

import (
"os"
"time"

"github.com/rs/zerolog"
"github.com/spf13/cobra"
)

const PaginationLimit = 1000

func Execute(configPath string) {
config, err := GetConfig(configPath)
if err != nil {
GetDefaultLogger().Fatal().Err(err).Msg("Could not load config")
}

if err = config.Validate(); err != nil {
GetDefaultLogger().Fatal().Err(err).Msg("Provided config is invalid!")
}

log := GetLogger(config.LogConfig)

stateManager := NewStateManager(config.StatePath, log)
reportGenerator := NewReportGenerator(stateManager, log, config.Chains)

for {
_ = reportGenerator.GenerateReport()
time.Sleep(time.Second * 30)
}
}

func main() {
var ConfigPath string

var rootCmd = &cobra.Command{
Use: "cosmos-proposals-checker",
Long: "Checks the specific wallets on different chains for proposal votes.",
Run: func(cmd *cobra.Command, args []string) {
Execute(ConfigPath)
},
}

rootCmd.PersistentFlags().StringVar(&ConfigPath, "config", "", "Config file path")
rootCmd.MarkPersistentFlagRequired("config")

if err := rootCmd.Execute(); err != nil {
log := zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout}).With().Timestamp().Logger()
log.Fatal().Err(err).Msg("Could not start application")
}
}
120 changes: 120 additions & 0 deletions report_generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package main

import (
"fmt"

"github.com/rs/zerolog"
)

type ReportGenerator struct {
StateManager *StateManager
Chains []Chain
RPC *RPC
Logger zerolog.Logger
}

type ReportEntry struct {
Chain string
Wallet string
ProposalId string
ProposalDescription string
Vote string
}

type Report struct {
Entries []ReportEntry
}

func NewReportGenerator(
manager *StateManager,
logger *zerolog.Logger,
chains []Chain,
) *ReportGenerator {
return &ReportGenerator{
StateManager: manager,
Chains: chains,
Logger: logger.With().Str("component", "report_generator").Logger(),
}
}

func (g *ReportGenerator) GenerateReport() *Report {
votesMap := make(map[string]map[string]map[string]*Vote)
proposalsMap := make(map[string][]Proposal)

for _, chain := range g.Chains {
votesMap[chain.Name] = make(map[string]map[string]*Vote)

rpc := NewRPC(chain.LCDEndpoints, g.Logger)

g.Logger.Info().Str("name", chain.Name).Msg("Processing a chain")
proposals, err := rpc.GetAllProposals()
if err != nil {
g.Logger.Warn().Err(err).Msg("Error processing proposals")
continue
}

g.Logger.Info().Int("len", len(proposals)).Msg("Got proposals")
proposalsMap[chain.Name] = proposals

for _, proposal := range proposals {
for _, wallet := range chain.Wallets {
if g.StateManager.HasVotedBefore(chain.Name, proposal.ProposalID, wallet) {
g.Logger.Trace().
Str("proposal", proposal.ProposalID).
Str("wallet", wallet).
Msg("Wallet has already voted, not checking again,")
continue
}

g.Logger.Info().
Str("proposal", proposal.ProposalID).
Str("wallet", wallet).
Msg("Checking if a wallet had voted")

vote, err := rpc.GetVote(proposal.ProposalID, wallet)
if err != nil {
g.Logger.Warn().Err(err).Msg("Error processing vote")
}

g.Logger.Info().Str("result", fmt.Sprintf("%+v", vote)).Msg("Got vote")
g.StateManager.SetVote(chain.Name, proposal.ProposalID, wallet, vote.Vote)
}
}
}

entries := []ReportEntry{}

for _, chain := range g.Chains {
for _, proposal := range proposalsMap[chain.Name] {
for _, wallet := range chain.Wallets {
votedNow := g.StateManager.HasVotedNow(chain.Name, proposal.ProposalID, wallet)
votedBefore := g.StateManager.HasVotedBefore(chain.Name, proposal.ProposalID, wallet)

// Hasn't voted for this proposal - need to notify.
if !votedNow {
entries = append(entries, ReportEntry{
Chain: chain.Name,
Wallet: wallet,
ProposalId: proposal.ProposalID,
ProposalDescription: proposal.Content.Description,
})
}

// Hasn't voted before but voted now - need to close alert/notify about new vote.
if votedNow && !votedBefore {
// entries = append(entries, ReportEntry{
// Chain: chain.Name,
// Wallet: wallet,
// ProposalId: proposal.ProposalID,
// ProposalDescription: proposal.Content.Description,
// Vote: ,
// })
}
}
}
}

g.StateManager.CommitNewState()

return &Report{}
}
Loading

0 comments on commit 1cb76ed

Please sign in to comment.