[[[cast_vote_prompt]]]
-
-
[[[voting_power]]]: {{$votingPower}}
-
-
-
-
-
-
-
+
+ [[[voting_power]]]: {{$votingPower}}
+
+
+
+
+
+
+
+
+
diff --git a/client/webserver/site/src/js/proposal.ts b/client/webserver/site/src/js/proposal.ts
index 3d3f6764ca..e0ba9123b8 100644
--- a/client/webserver/site/src/js/proposal.ts
+++ b/client/webserver/site/src/js/proposal.ts
@@ -107,6 +107,7 @@ export default class ProposalPage extends BasePage {
Doc.show(page.voteFormError)
return
}
+ Doc.hide(page.viewVoteFormBtn)
this.closePopups()
this.showSuccess(intl.prep(intl.ID_VOTE_CAST_MESSAGE))
}
diff --git a/dex/politeia/politeia.go b/dex/politeia/politeia.go
index eb67ad4b1e..53a587e52a 100644
--- a/dex/politeia/politeia.go
+++ b/dex/politeia/politeia.go
@@ -141,32 +141,45 @@ func New(ctx context.Context, politeiaURL string, dbPath string, log dex.Logger)
// have voted along with their votes, and the total yes and no votes cast by
// the wallet.
func (p *Politeia) WalletProposalVoteDetails(wallet VotingWallet, token string) (*WalletProposalVoteDetails, error) {
- req := tkv1.Results{
- Token: token,
- }
- votesResults, err := p.client.TicketVoteResults(req)
+ // Fetch the vote details to get the full list of eligible tickets
+ // from the snapshot.
+ voteDetails, err := p.client.TicketVoteDetails(tkv1.Details{Token: token})
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("TicketVoteDetails error: %w", err)
+ }
+ if voteDetails.Vote == nil {
+ return nil, fmt.Errorf("no vote details for proposal %s", token)
}
- hashes := make([]*chainhash.Hash, 0, len(votesResults.Votes))
- castVotes := make(map[string]string)
- for _, v := range votesResults.Votes {
- hash, err := chainhash.NewHashFromStr(v.Ticket)
+ // Build the list of all eligible ticket hashes from the vote snapshot.
+ eligibleHashes := make([]*chainhash.Hash, 0, len(voteDetails.Vote.EligibleTickets))
+ for _, ticketStr := range voteDetails.Vote.EligibleTickets {
+ hash, err := chainhash.NewHashFromStr(ticketStr)
if err != nil {
return nil, err
}
- hashes = append(hashes, hash)
+ eligibleHashes = append(eligibleHashes, hash)
+ }
+
+ // Fetch the votes already cast to know which tickets have voted.
+ votesResults, err := p.client.TicketVoteResults(tkv1.Results{Token: token})
+ if err != nil {
+ return nil, fmt.Errorf("TicketVoteResults error: %w", err)
+ }
+
+ castVotes := make(map[string]string, len(votesResults.Votes))
+ for _, v := range votesResults.Votes {
castVotes[v.Ticket] = v.VoteBit
}
- walletTicketHashes, addresses, err := wallet.CommittedTickets(hashes)
+ // Check which eligible tickets belong to this wallet.
+ walletTicketHashes, addresses, err := wallet.CommittedTickets(eligibleHashes)
if err != nil {
return nil, err
}
- eligibleWalletTickets := make([]*Ticket, 0) // eligibleWalletTickets are wallet tickets that have not yet voted.
- walletVotedTickets := make([]*Ticket, 0) // walletVotedTickets are wallet tickets that have voted.
+ eligibleWalletTickets := make([]*Ticket, 0)
+ walletVotedTickets := make([]*Ticket, 0)
for i := 0; i < len(walletTicketHashes); i++ {
ticket := &Ticket{
Hash: walletTicketHashes[i].String(),
@@ -176,17 +189,18 @@ func (p *Politeia) WalletProposalVoteDetails(wallet VotingWallet, token string)
isMine, accountNumber, err := wallet.AddressAccount(ticket.Address)
if err != nil {
if strings.Contains(err.Error(), "address not found in wallet") {
- continue // address not found in wallet, skip this ticket
+ continue
}
return nil, err
}
- // filter out tickets controlled by imported accounts or not owned by this wallet
+ // Filter out tickets controlled by imported accounts or not
+ // owned by this wallet.
if !isMine || accountNumber == udb.ImportedAddrAccount {
continue
}
- // filter out wallet tickets that have voted.
+ // Separate into already-voted and eligible.
if _, ok := castVotes[ticket.Hash]; ok {
walletVotedTickets = append(walletVotedTickets, ticket)
continue
@@ -262,6 +276,13 @@ func (p *Politeia) CastVotes(wallet VotingWallet, eligibleTickets []*Ticket, bit
return fmt.Errorf("errors casting votes: %v", strings.Join(voteErrors, "; "))
}
+ ticketHashes := make([]string, len(eligibleTickets))
+ for i, t := range eligibleTickets {
+ ticketHashes[i] = t.Hash
+ }
+ p.log.Infof("Successfully cast %d %s vote(s) on proposal %s with tickets: %s",
+ len(eligibleTickets), bit, token, strings.Join(ticketHashes, ", "))
+
return nil
}