Skip to content

Commit 444b220

Browse files
committed
add: making a DAO with random adresse from validator list
1 parent a3a3d8b commit 444b220

File tree

5 files changed

+98
-21
lines changed

5 files changed

+98
-21
lines changed

packages/r/greg007/gnobounty/application.gno

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,12 @@ func ApplyForBounty(_ realm, bountyID uint64, prLink string) uint64 {
5252
daoDesc := ufmt.Sprintf("Private DAO to review application for bounty #%d", bountyID)
5353

5454
// Create DAO with selected validators as members
55+
// DisableVotingDeadlineCheck allows immediate execution after votes
5556
dao := commondao.New(
5657
commondao.WithID(applicationCount),
5758
commondao.WithName(daoName),
5859
commondao.WithDescription(daoDesc),
60+
commondao.DisableVotingDeadlineCheck(),
5961
)
6062

6163
// Add selected validators as members
@@ -136,6 +138,22 @@ func Vote(_ realm, applicationID uint64, vote string) {
136138
if err != nil {
137139
panic(err)
138140
}
141+
142+
// Try to execute the proposal
143+
// Tally() will return true when all validators have voted
144+
// Execute() will handle both approval and rejection
145+
proposal = app.DAO.ActiveProposals().Get(app.ProposalID)
146+
if proposal != nil {
147+
totalMembers := app.DAO.Members().Size()
148+
totalVotes := proposal.VotingRecord().Size()
149+
150+
// If all validators have voted, execute to finalize
151+
if totalVotes == totalMembers {
152+
err = app.DAO.Execute(app.ProposalID)
153+
// Ignore errors - proposal might already be executed or failed
154+
// The status will be updated in Execute() regardless
155+
}
156+
}
139157
}
140158

141159
// GetApplicationsForBounty returns all applications for a specific bounty

packages/r/greg007/gnobounty/proposal.gno

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,28 +47,28 @@ func (p *ClaimBountyProposal) VotingPeriod() time.Duration {
4747
return 7 * 24 * time.Hour
4848
}
4949

50-
// Tally counts votes and determines if proposal passes
51-
// Requires all 3 validators to vote YES for approval
50+
// Tally counts votes and determines if proposal is ready to execute
51+
// Returns true when all validators have voted (regardless of outcome)
5252
func (p *ClaimBountyProposal) Tally(votes commondao.ReadonlyVotingRecord, members commondao.MemberSet) (bool, error) {
5353
totalMembers := members.Size()
5454
if totalMembers == 0 {
5555
return false, ufmt.Errorf("no members in DAO")
5656
}
5757

58-
// Count votes using the VoteCount method
59-
yesCount := votes.VoteCount(commondao.ChoiceYes)
60-
noCount := votes.VoteCount(commondao.ChoiceNo)
58+
totalVotes := votes.Size()
6159

62-
// Require 100% approval: all validators must vote YES
63-
// For a 3-validator DAO, we need exactly 3 YES votes
64-
if yesCount == totalMembers && noCount == 0 {
60+
// Return true when all validators have voted
61+
// This allows Execute to be called and handle approval/rejection
62+
if totalVotes == totalMembers {
6563
return true, nil
6664
}
6765

66+
// Not ready yet - waiting for more votes
6867
return false, nil
6968
}
7069

71-
// Execute executes the proposal after approval
70+
// Execute executes the proposal after all votes are in
71+
// Determines approval or rejection based on vote counts
7272
func (p *ClaimBountyProposal) Execute(_ realm) error {
7373
app := GetApplication(p.ApplicationID)
7474
if app == nil {
@@ -84,19 +84,34 @@ func (p *ClaimBountyProposal) Execute(_ realm) error {
8484
return ufmt.Errorf("bounty already claimed")
8585
}
8686

87-
// Mark application as approved
88-
app.Status = StatusApproved
87+
// Get vote counts from the DAO proposal
88+
proposal := app.DAO.ActiveProposals().Get(app.ProposalID)
89+
if proposal == nil {
90+
return ufmt.Errorf("proposal not found")
91+
}
8992

90-
// Mark bounty as claimed
91-
bounty.IsClaimed = true
92-
bounty.Claimer = p.Applicant
93-
bounty.ClaimedAt = time.Now()
93+
yesCount := proposal.VotingRecord().VoteCount(commondao.ChoiceYes)
94+
noCount := proposal.VotingRecord().VoteCount(commondao.ChoiceNo)
95+
totalMembers := app.DAO.Members().Size()
9496

95-
// Transfer bounty amount to applicant
96-
bnk := banker.NewBanker(banker.BankerTypeRealmSend)
97-
send := chain.Coins{chain.Coin{Denom: "ugnot", Amount: bounty.Amount}}
98-
pkgAddr := chain.PackageAddress("gno.land/r/greg007/gnobounty")
99-
bnk.SendCoins(pkgAddr, p.Applicant, send)
97+
// Check if unanimous approval (all YES, no NO)
98+
if yesCount == totalMembers && noCount == 0 {
99+
// Approve and transfer funds
100+
app.Status = StatusApproved
101+
102+
bounty.IsClaimed = true
103+
bounty.Claimer = p.Applicant
104+
bounty.ClaimedAt = time.Now()
105+
106+
// Transfer bounty amount to applicant
107+
bnk := banker.NewBanker(banker.BankerTypeRealmSend)
108+
send := chain.Coins{chain.Coin{Denom: "ugnot", Amount: bounty.Amount}}
109+
pkgAddr := chain.PackageAddress("gno.land/r/greg007/gnobounty")
110+
bnk.SendCoins(pkgAddr, p.Applicant, send)
111+
} else {
112+
// Reject - not unanimous
113+
app.Status = StatusRejected
114+
}
100115

101116
return nil
102117
}

packages/r/greg007/gnobounty/render.gno

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,51 @@ func renderApplication(app *Application) string {
137137
// Show DAO voting information if DAO exists
138138
if app.DAO != nil {
139139
output += ufmt.Sprintf("- Proposal ID: %d\n", app.ProposalID)
140-
output += ufmt.Sprintf("- Validators: %d assigned\n", app.DAO.Members().Size())
140+
141+
// Get proposal and show detailed validator voting status
142+
proposal := app.DAO.ActiveProposals().Get(app.ProposalID)
143+
if proposal != nil {
144+
// Get vote counts
145+
yesCount := proposal.VotingRecord().VoteCount(commondao.ChoiceYes)
146+
noCount := proposal.VotingRecord().VoteCount(commondao.ChoiceNo)
147+
abstainCount := proposal.VotingRecord().VoteCount(commondao.ChoiceAbstain)
148+
totalVotes := proposal.VotingRecord().Size()
149+
totalMembers := app.DAO.Members().Size()
150+
151+
output += ufmt.Sprintf("\n**Voting Progress:** %d/%d validators have voted\n", totalVotes, totalMembers)
152+
output += ufmt.Sprintf("- ✅ YES: %d\n", yesCount)
153+
output += ufmt.Sprintf("- ❌ NO: %d\n", noCount)
154+
output += ufmt.Sprintf("- 🤷 ABSTAIN: %d\n", abstainCount)
155+
output += ufmt.Sprintf("- ⏳ PENDING: %d\n", totalMembers-totalVotes)
156+
}
157+
}
158+
159+
// Add vote buttons for validators if application is still pending
160+
if app.Status == StatusPending && app.DAO != nil {
161+
output += "\n**Vote on this application:**\n"
162+
163+
// Add vote buttons (yes/no/abstain)
164+
yesLink := txlink.NewLink("Vote").
165+
AddArgs(
166+
"applicationID", ufmt.Sprintf("%d", app.ID),
167+
"vote", "yes",
168+
).
169+
URL()
170+
noLink := txlink.NewLink("Vote").
171+
AddArgs(
172+
"applicationID", ufmt.Sprintf("%d", app.ID),
173+
"vote", "no",
174+
).
175+
URL()
176+
abstainLink := txlink.NewLink("Vote").
177+
AddArgs(
178+
"applicationID", ufmt.Sprintf("%d", app.ID),
179+
"vote", "abstain",
180+
).
181+
URL()
182+
183+
output += md.Link("✅ Approve", yesLink) + " | " + md.Link("❌ Reject", noLink) + " | " + md.Link("🤷 Abstain", abstainLink) + "\n"
184+
output += "\n_Note: Only assigned validators can vote on this application._\n"
141185
}
142186
output += "\n"
143187

0 commit comments

Comments
 (0)