Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

proposal_status.gno

7.79 Kb · 252 lines
  1package governance
  2
  3import (
  4	gnsmath "gno.land/p/gnoswap/gnsmath/v1"
  5
  6	"gno.land/r/gnoswap/gov/governance"
  7)
  8
  9type ProposalStatusResolver struct {
 10	*governance.ProposalStatus
 11	scheduleResolver     *ProposalScheduleStatusResolver
 12	actionStatusResolver *ProposalActionStatusResolver
 13	voteStatusResolver   *ProposalVoteStatusResolver
 14}
 15
 16// NewProposalStatusResolver wraps proposal status components for lifecycle and vote queries.
 17//
 18// Parameters:
 19//   - status: proposal status containing schedule, action, and vote state
 20//
 21// Returns:
 22//   - *ProposalStatusResolver: resolver backed by status
 23func NewProposalStatusResolver(status *governance.ProposalStatus) *ProposalStatusResolver {
 24	return &ProposalStatusResolver{
 25		ProposalStatus:       status,
 26		scheduleResolver:     NewProposalScheduleStatusResolver(status.Schedule()),
 27		actionStatusResolver: NewProposalActionStatusResolver(status.ActionStatus()),
 28		voteStatusResolver:   NewProposalVoteStatusResolver(status.VoteStatus()),
 29	}
 30}
 31
 32// TotalVoteWeight returns the total weight of all votes cast.
 33//
 34// Returns:
 35//   - int64: total vote weight
 36func (p *ProposalStatusResolver) TotalVoteWeight() int64 {
 37	return p.voteStatusResolver.TotalVoteWeight()
 38}
 39
 40// StatusType determines the current status of the proposal based on timing, voting, and actions.
 41// This is the main status calculation method that considers all factors.
 42//
 43// Parameters:
 44//   - current: current timestamp to evaluate status at
 45//
 46// Returns:
 47//   - ProposalStatusType: current status of the proposal
 48func (p *ProposalStatusResolver) StatusType(current int64) governance.ProposalStatusType {
 49	actionStatus := p.ActionStatus()
 50
 51	// Check action-based statuses first (these override time-based statuses)
 52	if actionStatus.IsExecuted() {
 53		return governance.StatusExecuted
 54	}
 55
 56	if actionStatus.Canceled() {
 57		return governance.StatusCanceled
 58	}
 59
 60	// Check time-based statuses
 61	if !p.scheduleResolver.IsPassedActiveAt(current) {
 62		return governance.StatusUpcoming
 63	}
 64
 65	if !p.scheduleResolver.IsPassedVotingEndedAt(current) {
 66		return governance.StatusActive
 67	}
 68
 69	// Check voting outcome after voting period ends
 70	if !p.voteStatusResolver.IsPassed() {
 71		return governance.StatusRejected
 72	}
 73
 74	// For passed proposals, check execution status
 75	if !p.ActionStatus().IsExecutable() || !p.scheduleResolver.IsPassedExecutableAt(current) {
 76		return governance.StatusPassed
 77	}
 78
 79	if !p.scheduleResolver.IsPassedExpiredAt(current) {
 80		return governance.StatusExecutable
 81	}
 82
 83	return governance.StatusExpired
 84}
 85
 86// IsUpcoming checks if the proposal is in upcoming status.
 87//
 88// Parameters:
 89//   - current: timestamp to check status at
 90//
 91// Returns:
 92//   - bool: true if proposal is upcoming
 93func (p *ProposalStatusResolver) IsUpcoming(current int64) bool {
 94	return p.StatusType(current) == governance.StatusUpcoming
 95}
 96
 97// IsActive checks if the proposal is in active voting status.
 98//
 99// Parameters:
100//   - current: timestamp to check status at
101//
102// Returns:
103//   - bool: true if proposal is active (voting period)
104func (p *ProposalStatusResolver) IsActive(current int64) bool {
105	return p.StatusType(current) == governance.StatusActive
106}
107
108// IsPassed checks if the proposal has passed voting.
109//
110// Parameters:
111//   - current: timestamp to check status at
112//
113// Returns:
114//   - bool: true if proposal has passed
115func (p *ProposalStatusResolver) IsPassed(current int64) bool {
116	return p.StatusType(current) == governance.StatusPassed
117}
118
119// IsRejected checks if the proposal has been rejected by voting.
120//
121// Parameters:
122//   - current: timestamp to check status at
123//
124// Returns:
125//   - bool: true if proposal was rejected
126func (p *ProposalStatusResolver) IsRejected(current int64) bool {
127	return p.StatusType(current) == governance.StatusRejected
128}
129
130// IsExecutable checks if the proposal is in executable status.
131//
132// Parameters:
133//   - current: timestamp to check status at
134//
135// Returns:
136//   - bool: true if proposal can be executed
137func (p *ProposalStatusResolver) IsExecutable(current int64) bool {
138	return p.StatusType(current) == governance.StatusExecutable
139}
140
141// IsExpired checks if the proposal execution window has expired.
142//
143// Parameters:
144//   - current: timestamp to check status at
145//
146// Returns:
147//   - bool: true if proposal has expired
148func (p *ProposalStatusResolver) IsExpired(current int64) bool {
149	return p.StatusType(current) == governance.StatusExpired
150}
151
152// IsExecuted checks if the proposal has been executed.
153//
154// Parameters:
155//   - current: timestamp to check status at
156//
157// Returns:
158//   - bool: true if proposal has been executed
159func (p *ProposalStatusResolver) IsExecuted(current int64) bool {
160	return p.StatusType(current) == governance.StatusExecuted
161}
162
163// IsCanceled checks if the proposal has been canceled.
164//
165// Parameters:
166//   - current: timestamp to check status at
167//
168// Returns:
169//   - bool: true if proposal has been canceled
170func (p *ProposalStatusResolver) IsCanceled(current int64) bool {
171	return p.StatusType(current) == governance.StatusCanceled
172}
173
174// cancel marks the proposal as canceled with the provided details.
175// This delegates to the action status for actual cancellation logic.
176//
177// Parameters:
178//   - canceledAt: timestamp when proposal was canceled
179//   - canceledHeight: block height when proposal was canceled
180//   - canceledBy: address that canceled the proposal
181//
182// Returns:
183//   - error: cancellation error if operation fails
184func (p *ProposalStatusResolver) cancel(canceledAt int64, canceledHeight int64, canceledBy address) error {
185	return p.actionStatusResolver.cancel(canceledAt, canceledHeight, canceledBy)
186}
187
188// execute marks the proposal as executed with the provided details.
189// This delegates to the action status for actual execution logic.
190//
191// Parameters:
192//   - executedAt: timestamp when proposal was executed
193//   - executedHeight: block height when proposal was executed
194//   - executedBy: address that executed the proposal
195//
196// Returns:
197//   - error: execution error if operation fails
198func (p *ProposalStatusResolver) execute(executedAt int64, executedHeight int64, executedBy address) error {
199	return p.actionStatusResolver.Execute(executedAt, executedHeight, executedBy)
200}
201
202// vote records a vote on the proposal and updates vote tallies.
203// This delegates to the vote status for actual vote recording.
204//
205// Parameters:
206//   - votedYes: true for "yes" vote, false for "no" vote
207//   - weight: voting weight to apply
208//
209// Returns:
210//   - error: voting error if operation fails
211func (p *ProposalStatusResolver) vote(votedYes bool, weight int64) error {
212	if votedYes {
213		return p.voteStatusResolver.AddYesVoteWeight(weight)
214	}
215
216	return p.voteStatusResolver.AddNoVoteWeight(weight)
217}
218
219// NewProposalStatus creates a new proposal status with the specified configuration.
220// This initializes all status components with the governance configuration and timing.
221//
222// Parameters:
223//   - config: governance configuration to use
224//   - maxVotingWeight: maximum voting weight for this proposal
225//   - executable: whether this proposal type can be executed
226//   - createdAt: timestamp when proposal was created
227//   - quorumWeight: total xGNS supply at proposal creation, used as the quorum base
228//
229// Returns:
230//   - *ProposalStatus: new proposal status instance
231func NewProposalStatus(
232	config governance.Config,
233	maxVotingWeight int64,
234	executable bool,
235	createdAt int64,
236	quorumWeight int64,
237) *governance.ProposalStatus {
238	schedule := NewProposalScheduleStatus(
239		config.VotingStartDelay,
240		config.VotingPeriod,
241		config.ExecutionDelay,
242		config.ExecutionWindow,
243		createdAt,
244	)
245	actionStatus := governance.NewProposalActionStatus(executable)
246
247	// Calculate the quorum amount from the current xGNS supply, not the smoothed voting weight.
248	quorumAmount := gnsmath.SafeMulDivInt64(quorumWeight, config.Quorum, 100)
249	voteStatus := governance.NewProposalVoteStatus(maxVotingWeight, quorumAmount)
250
251	return governance.NewProposalStatusBy(schedule, actionStatus, voteStatus)
252}