Skip to content

Comments

feat: Add a Poll package and realm.#3980

Closed
wyhaines wants to merge 4 commits intomasterfrom
kh.add-poll-package-and-realm-v2
Closed

feat: Add a Poll package and realm.#3980
wyhaines wants to merge 4 commits intomasterfrom
kh.add-poll-package-and-realm-v2

Conversation

@wyhaines
Copy link
Contributor

This is a simple polling package and realm. It allows the creation of multi-option polls with the ability to vote for more than one option.

It was based off of Leon's simple polling realm in the docs, but expanded to handle any number of polls with any number of options.

This branch supercedes kh.add-poll-package-and-realm, and this PR replaces #3776. It was far simpler to just make a completely clean new branch with the code than to try to clean up an old rebase.

… Together, these provide a way to run polls using gno.land.
@github-actions github-actions bot added the 🧾 package/realm Tag used for new Realms or Packages. label Mar 19, 2025
@Gno2D2 Gno2D2 requested a review from a team March 19, 2025 22:53
@Gno2D2 Gno2D2 added the review/triage-pending PRs opened by external contributors that are waiting for the 1st review label Mar 19, 2025
@Gno2D2
Copy link
Collaborator

Gno2D2 commented Mar 19, 2025

🛠 PR Checks Summary

🔴 Pending initial approval by a review team member, or review from tech-staff

Manual Checks (for Reviewers):
  • IGNORE the bot requirements for this PR (force green CI check)
  • The pull request description provides enough details (checked by @thehowl)
Read More

🤖 This bot helps streamline PR reviews by verifying automated checks and providing guidance for contributors and reviewers.

✅ Automated Checks (for Contributors):

🔴 Pending initial approval by a review team member, or review from tech-staff

☑️ Contributor Actions:
  1. Fix any issues flagged by automated checks.
  2. Follow the Contributor Checklist to ensure your PR is ready for review.
    • Add new tests, or document why they are unnecessary.
    • Provide clear examples/screenshots, if necessary.
    • Update documentation, if required.
    • Ensure no breaking changes, or include BREAKING CHANGE notes.
    • Link related issues/PRs, where applicable.
☑️ Reviewer Actions:
  1. Complete manual checks for the PR, including the guidelines and additional checks if applicable.
📚 Resources:
Debug
Automated Checks
Pending initial approval by a review team member, or review from tech-staff

If

🟢 Condition met
└── 🟢 And
    ├── 🟢 The base branch matches this pattern: ^master$
    └── 🟢 Not (🔴 Pull request author is a member of the team: tech-staff)

Then

🔴 Requirement not satisfied
└── 🔴 If
    ├── 🟢 Condition
    │   └── 🟢 Or
    │       ├── 🟢 At least 1 user(s) of the organization reviewed the pull request (with state "APPROVED")
    │       ├── 🔴 At least 1 user(s) of the team tech-staff reviewed pull request
    │       └── 🟢 This pull request is a draft
    └── 🔴 Then
        └── 🔴 And
            ├── 🟢 Not (🔴 This label is applied to pull request: review/triage-pending)
            └── 🔴 At least 1 user(s) of the team tech-staff reviewed pull request

Manual Checks
**IGNORE** the bot requirements for this PR (force green CI check)

If

🟢 Condition met
└── 🟢 On every pull request

Can be checked by

  • Any user with comment edit permission
The pull request description provides enough details

If

🟢 Condition met
└── 🟢 And
    ├── 🟢 Not (🔴 Pull request author is a member of the team: core-contributors)
    └── 🟢 Not (🔴 Pull request author is user: dependabot[bot])

Can be checked by

  • team core-contributors

@jefft0
Copy link
Contributor

jefft0 commented Mar 20, 2025

Hi @wyhaines . The API allows to edit option text. This means that the poll owner can do:

AddOption("0000001", "yes")
AddOption("0000001", "no")

Then let a bunch of people vote. Then switch the options:

EditOption("0000001", 0, "no")
EditOption("0000001", 1, "yes")

If this was a vote on an important topic, then this could be a security risk. What do you think? Should there be a limit to editing the poll options after voting starts?

@michelleellen michelleellen requested review from jefft0 and leohhhn March 20, 2025 20:02
@wyhaines
Copy link
Contributor Author

@jefft0 that is a good catch. I'll add a guard to prevent changing of the poll options after the first vote is cast. That seems reasonable to me.

@codecov
Copy link

codecov bot commented Mar 26, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Contributor

@jefft0 jefft0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. My security concern was addressed about not editing the poll after voting starts. Good test coverage.

@Gno2D2 Gno2D2 removed the review/triage-pending PRs opened by external contributors that are waiting for the 1st review label Mar 27, 2025
@michelleellen michelleellen requested a review from moul March 31, 2025 12:06
@Kouteki Kouteki requested review from petar-dambovaliev and removed request for a team April 3, 2025 11:47
@Kouteki Kouteki moved this from Triage to In Review in 🧙‍♂️Gno.land development Apr 3, 2025
@michelleellen
Copy link
Contributor

Hey @petar-dambovaliev @leohhhn do you have any reviews for this?

Copy link
Contributor

@leohhhn leohhhn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the slow turnaround 🙏

Left some comments; I think that there's a few best practices we can put into this code to make it better.

Txlinks would be a great addition to the app, especially now since we have the Adena integration. Could you please post a few screenshots of how the app would look like

Comment on lines +53 to +54
_, exists := p.Votes.Get(addr.String())
return exists
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use avl.Tree.Has

}

// VoterCount returns how many unique addresses have cast votes.
func (p *Poll) VoterCount() int {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this func is readonly so no need for a pointer receiver

Suggested change
func (p *Poll) VoterCount() int {
func (p Poll) VoterCount() int {

Comment on lines +138 to +139
//----------------------------------------
// Rendering
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's move this to a render.gno file

Comment on lines +159 to +164
func renderSinglePoll(b *bytes.Buffer, id string, p *poll.Poll) {
b.WriteString(ufmt.Sprintf("# Poll %s: %s\n\n", id, p.Title))
b.WriteString(ufmt.Sprintf("**Description:** %s\n\n", p.Description))
b.WriteString(ufmt.Sprintf("**Deadline:** %s\n", p.Deadline.Format(time.RFC1123)))
b.WriteString(ufmt.Sprintf("**Creator:** %s\n", p.Creator))
b.WriteString(ufmt.Sprintf("**MaxChoices:** %d\n", p.MaxChoices))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what your opinion is but I much more prefer that functions do not mutate their args. So ideally we'd just return a simple string here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also code is more readable with out := "" instead of WriteString, and we don't care too much about the saving on computation since this function is queried

Comment on lines +144 to +152
path = strings.TrimSpace(path)
if path == "" || strings.HasPrefix(path, "page=") {
return renderPollList(&b, path)
}

val, exists := polls.Get(path)
if !exists {
return renderPollList(&b, "")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could use p/demo/mux here. https://gno.land/r/docs/routing

Comment on lines +25 to +27
func init() {
polls = avl.NewTree()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can just init this at the var block

var (
polls *avl.Tree // TODO: This would be better as a btree; no need to key off a string, then.
pollIDCounter seqid.ID
pageSize = 5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be const?

Comment on lines +50 to +51
newP := poll.NewPoll(title, description, []string{}, maxChoices, deadline, caller)
polls.Set(id, newP)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found it generally easier to set the value to the address instead of the value itself; this allows you to modify the value a bit more easily down the line (ie directly modify after getting it from the tree, and not having to set again)

newP := poll.NewPoll(title, description, []string{}, maxChoices, deadline, caller)
polls.Set(id, newP)

return ufmt.Sprintf("Successfully created poll #%s!", id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this string useful for anything?

I'd much rather have a std.Emit(), and a good render UI with txlinks for specific polls

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for other functions

Comment on lines +79 to +81
if p.Creator != std.OriginCaller() {
panic("only the poll creator can add options")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing for OriginCaller

@wyhaines
Copy link
Contributor Author

Txlinks would be a great addition to the app, especially now since we have the Adena integration. Could you please post a few screenshots of how the app would look like

I only discovered txlink last week. This is a big issue, in general, for development with gno.land. Discoverability for the libs that we have is difficult. I'll take a look at how it could make the gnoweb based UI better.

@jefft0
Copy link
Contributor

jefft0 commented May 28, 2025

Hi @wyhaines . Are you able to address the comments from @leohhhn ?

@leohhhn leohhhn marked this pull request as draft May 28, 2025 11:10
@Kouteki Kouteki moved this from In Review to Todo in 🧙‍♂️Gno.land development Jun 2, 2025
@github-actions
Copy link

This PR is stale because it has been open 3 months with no activity. Remove stale label or comment or this will be closed in 3 months.

@github-actions github-actions bot added Stale and removed Stale labels Aug 27, 2025
@leohhhn
Copy link
Contributor

leohhhn commented Aug 28, 2025

Closing as stale; @wyhaines please feel free to reopen if you want to keep working on this :)

@leohhhn leohhhn closed this Aug 28, 2025
@github-project-automation github-project-automation bot moved this from In Progress to Done in 💪 Bounties & Worx Aug 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🧾 package/realm Tag used for new Realms or Packages.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants