-
Hugo Trentesaux authoredHugo Trentesaux authored
collective.rs 3.33 KiB
use crate::*;
use anyhow::Result;
/// define technical committee subcommands
#[derive(Clone, Default, Debug, clap::Parser)]
pub enum Subcommand {
#[default]
/// List members of the technical committee
Members,
/// List proposals to the technical committee
Proposals,
/// Vote a proposal to the technical committee
Vote {
/// Proposal hash
hash: Hash,
/// Proposal index
index: u32,
/// Vote (0=against, 1=for)
vote: u8,
},
}
/// handle technical committee commands
pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliError> {
let mut data = data.build_client().await?.build_indexer().await?;
match command {
Subcommand::Members => {
data = data.build_client().await?;
commands::collective::technical_committee_members(&data).await?
}
Subcommand::Proposals => {
data = data.build_client().await?;
commands::collective::technical_committee_proposals(data.client()).await?
}
Subcommand::Vote { hash, index, vote } => {
data = data.build_client().await?;
let vote = match vote {
0 => false,
1 => true,
_ => panic!("Vote must be written 0 if you disagree, or 1 if you agree."),
};
commands::collective::technical_committee_vote(
&data, hash, //Hash::from_str(&hash).expect("Invalid hash formatting"),
index, vote,
)
.await?;
}
};
Ok(())
}
/// list technical committee members
pub async fn technical_committee_members(data: &Data) -> Result<()> {
let client = data.client();
let indexer = data.indexer.clone();
let parent_hash = client
.storage()
.at_latest()
.await?
.fetch(&runtime::storage().system().parent_hash())
.await?
.unwrap();
for account_id in client
.storage()
.at(parent_hash)
.fetch(&runtime::storage().technical_committee().members())
.await?
.unwrap_or_default()
{
println!(
"{}",
if let Some(indexer) = &indexer {
indexer
.username_by_pubkey(&account_id.to_string())
.await
.ok()
.flatten()
} else {
client
.storage()
.at(parent_hash)
.fetch(&runtime::storage().identity().identity_index_of(&account_id))
.await
.ok()
.flatten()
.map(|identity_id| format!("{identity_id}"))
}
.unwrap_or_else(|| account_id.to_string(),)
);
}
Ok(())
}
/// list technical committee proposals
// TODO:
// * better formatting (format pubkeys to SS58 and add usernames)
// * display proposals indices
pub async fn technical_committee_proposals(client: &Client) -> Result<()> {
let parent_hash = client
.storage()
.at_latest()
.await?
.fetch(&runtime::storage().system().parent_hash())
.await?
.unwrap();
let mut proposals_iter = client
.storage()
.at(parent_hash)
.iter(runtime::storage().technical_committee().proposal_of_iter())
.await?;
while let Some(Ok((proposal_hash, proposal))) = proposals_iter.next().await {
println!("{}", hex::encode(&proposal_hash[32..64]));
println!("{proposal:#?}");
println!();
}
Ok(())
}
/// submit vote to technical committee
pub async fn technical_committee_vote(
data: &Data,
proposal_hash: Hash,
proposal_index: u32,
vote: bool,
) -> Result<(), subxt::Error> {
submit_call_and_look_event::<
runtime::technical_committee::events::Voted,
Payload<runtime::technical_committee::calls::types::Vote>,
>(
data,
&runtime::tx()
.technical_committee()
.vote(proposal_hash, proposal_index, vote),
)
.await
}