From 5b7bf2f22be2f07bbc42ed92496036695f298a26 Mon Sep 17 00:00:00 2001 From: Techno Freak Date: Sat, 23 Dec 2023 02:55:18 +0300 Subject: [PATCH] feat: add Neutron tallies fetching --- pkg/fetchers/neutron/responses/proposals.go | 78 +++++++++++++++++++-- pkg/fetchers/neutron/tally.go | 34 ++++++++- 2 files changed, 102 insertions(+), 10 deletions(-) diff --git a/pkg/fetchers/neutron/responses/proposals.go b/pkg/fetchers/neutron/responses/proposals.go index 76c4600..278c704 100644 --- a/pkg/fetchers/neutron/responses/proposals.go +++ b/pkg/fetchers/neutron/responses/proposals.go @@ -5,6 +5,8 @@ import ( "main/pkg/utils" "strconv" "time" + + "cosmossdk.io/math" ) type ProposalWithID struct { @@ -19,6 +21,12 @@ type Proposal struct { } `json:"expiration"` Status string `json:"status"` TotalPower string `json:"total_power"` + + Votes struct { + Yes string `json:"yes"` + No string `json:"no"` + Abstain string `json:"abstain"` + } `json:"votes"` } type ProposalsResponse struct { @@ -35,18 +43,74 @@ func (p ProposalsResponse) ToProposals() ([]types.Proposal, error) { proposals := make([]types.Proposal, len(allProposals)) for index, proposal := range allProposals { - expiresAt, err := strconv.ParseInt(proposal.Proposal.Expiration.AtTime, 10, 64) + proposalParsed, err := proposal.ToProposal() if err != nil { return nil, err } - proposals[index] = types.Proposal{ - ID: strconv.Itoa(proposal.ID), - Title: proposal.Proposal.Title, - Description: proposal.Proposal.Description, - EndTime: time.Unix(0, expiresAt), - } + proposals[index] = proposalParsed } return proposals, nil } + +func (p ProposalWithID) ToProposal() (types.Proposal, error) { + expiresAt, err := strconv.ParseInt(p.Proposal.Expiration.AtTime, 10, 64) + if err != nil { + return types.Proposal{}, err + } + + return types.Proposal{ + ID: strconv.Itoa(p.ID), + Title: p.Proposal.Title, + Description: p.Proposal.Description, + EndTime: time.Unix(0, expiresAt), + }, nil +} + +func (p ProposalsResponse) ToTally() ([]types.TallyInfo, error) { + allProposals := utils.Filter(p.Data.Proposals, func(p ProposalWithID) bool { + return p.Proposal.Status == "open" + }) + + tallyInfos := make([]types.TallyInfo, len(allProposals)) + + for index, proposal := range allProposals { + proposalParsed, err := proposal.ToProposal() + if err != nil { + return []types.TallyInfo{}, err + } + + yesVotes, err := math.LegacyNewDecFromStr(proposal.Proposal.Votes.Yes) + if err != nil { + return []types.TallyInfo{}, err + } + + noVotes, err := math.LegacyNewDecFromStr(proposal.Proposal.Votes.No) + if err != nil { + return []types.TallyInfo{}, err + } + + abstainVotes, err := math.LegacyNewDecFromStr(proposal.Proposal.Votes.Abstain) + if err != nil { + return []types.TallyInfo{}, err + } + + totalVotes, err := math.LegacyNewDecFromStr(proposal.Proposal.TotalPower) + if err != nil { + return []types.TallyInfo{}, err + } + + tallyInfos[index] = types.TallyInfo{ + Proposal: proposalParsed, + Tally: types.Tally{ + {Option: "Yes", Voted: yesVotes}, + {Option: "No", Voted: noVotes}, + {Option: "Abstain", Voted: abstainVotes}, + }, + TotalVotingPower: totalVotes, + } + } + + return tallyInfos, nil +} diff --git a/pkg/fetchers/neutron/tally.go b/pkg/fetchers/neutron/tally.go index 5d8f042..74be8c8 100644 --- a/pkg/fetchers/neutron/tally.go +++ b/pkg/fetchers/neutron/tally.go @@ -1,8 +1,36 @@ package neutron -import "main/pkg/types" +import ( + "encoding/base64" + "fmt" + "main/pkg/fetchers/neutron/responses" + "main/pkg/types" +) func (fetcher *Fetcher) GetTallies() (types.ChainTallyInfos, error) { - // TODO: fix - return types.ChainTallyInfos{}, nil + query := base64.StdEncoding.EncodeToString([]byte("{\"list_proposals\": {}}")) + + url := fmt.Sprintf( + "/cosmwasm/wasm/v1/contract/%s/smart/%s", + fetcher.ChainConfig.NeutronSmartContract, + query, + ) + + var proposals responses.ProposalsResponse + if errs := fetcher.Client.Get(url, &proposals); len(errs) > 0 { + return types.ChainTallyInfos{}, &types.QueryError{ + QueryError: nil, + NodeErrors: errs, + } + } + + tallyInfos, err := proposals.ToTally() + if err != nil { + return types.ChainTallyInfos{}, err + } + + return types.ChainTallyInfos{ + Chain: fetcher.ChainConfig, + TallyInfos: tallyInfos, + }, nil }