Skip to content

Commit

Permalink
improve client UX for voting on proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
brentstone committed Mar 6, 2024
1 parent f40e225 commit d3a5846
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 10 deletions.
9 changes: 9 additions & 0 deletions crates/sdk/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,15 @@ pub enum TxSubmitError {
/// No bonds found
#[error("No bonds found")]
NoBondFound,
/// No delegations found at epoch
#[error("The account {0} has no active delegations found at epoch {1}")]
NoDelegationsFound(Address, Epoch),
/// Cannot vote in governance
#[error(
"Validator {0} cannot vote in governance because the validator is \
either jailed or inactive at the current epoch {1}"
)]
CannotVoteInGovernance(Address, Epoch),
/// Lower bond amount than the unbond
#[error(
"The total bonds of the source {0} is lower than the amount to be \
Expand Down
58 changes: 48 additions & 10 deletions crates/sdk/src/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1961,6 +1961,26 @@ pub async fn build_vote_proposal(
let is_validator =
rpc::is_validator(context.client(), voter_address).await?;

// Prevent jailed or inactive validators from voting
if is_validator && !tx.force {
let state = rpc::get_validator_state(
context.client(),
voter_address,
Some(current_epoch),
)
.await?;
if matches!(
state,
Some(ValidatorState::Jailed) | Some(ValidatorState::Inactive)
) {
return Err(Error::from(TxSubmitError::CannotVoteInGovernance(
voter_address.clone(),
current_epoch,
)));
}
}

// Check if the voting period is still valid for the voter
if !proposal.can_be_voted(current_epoch, is_validator) {
if tx.force {
eprintln!("Invalid proposal {} vote period.", proposal_id);
Expand All @@ -1971,20 +1991,38 @@ pub async fn build_vote_proposal(
}
}

let delegations = rpc::get_delegations_of_delegator_at(
// Get active valid validators with whom the voter has delegations (bonds)
let delegation_vals = rpc::get_delegation_validators(
context.client(),
voter_address,
proposal.voting_start_epoch,
)
.await?
.keys()
.cloned()
.collect::<Vec<Address>>();

if delegations.is_empty() {
return Err(Error::Other(
"Voter address must have delegations".to_string(),
));
.await?;

let mut delegation_validators = Vec::<Address>::new();
for validator in delegation_vals {
let val_state = rpc::get_validator_state(
context.client(),
&validator,
Some(current_epoch),
)
.await
.expect("Expected to find the state of the validator");
if !matches!(
val_state,
Some(ValidatorState::Jailed) | Some(ValidatorState::Inactive)
) {
continue;
}
delegation_validators.push(validator);
}

// Check that there are delegations to vote with
if delegation_validators.is_empty() && !tx.force {
return Err(Error::from(TxSubmitError::NoDelegationsFound(
voter_address.clone(),
current_epoch,
)));
}

let data = VoteProposalData {
Expand Down

0 comments on commit d3a5846

Please sign in to comment.