diff --git a/Cargo.lock b/Cargo.lock index cef94b71..526cc91f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2109,7 +2109,7 @@ dependencies = [ [[package]] name = "encointer-client-notee" -version = "1.8.0" +version = "1.8.1" dependencies = [ "clap 2.34.0", "clap-nested", @@ -2123,6 +2123,7 @@ dependencies = [ "futures", "geojson", "hex", + "itertools 0.10.5", "log", "pallet-encointer-balances", "pallet-encointer-ceremonies", @@ -2158,7 +2159,7 @@ dependencies = [ [[package]] name = "encointer-node-notee" -version = "1.8.0" +version = "1.8.1" dependencies = [ "clap 4.5.1", "encointer-balances-tx-payment-rpc", diff --git a/client/Cargo.toml b/client/Cargo.toml index 14bc6d62..e26a103e 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -3,7 +3,7 @@ name = "encointer-client-notee" authors = ["encointer.org "] edition = "2021" #keep with node version. major, minor and patch -version = "1.8.0" +version = "1.8.1" [dependencies] # todo migrate to clap >=3 https://github.com/encointer/encointer-node/issues/107 @@ -37,6 +37,7 @@ substrate-client-keystore = { workspace = true } # substrate deps frame-support = { workspace = true, features = ["std"] } frame-system = { workspace = true, features = ["std"] } +itertools = "0.10.5" pallet-transaction-payment = { workspace = true, features = ["std"] } sp-application-crypto = { workspace = true, features = ["std"] } sp-core = { workspace = true, features = ["std"] } diff --git a/client/encointer-api-client-extension/src/ceremonies.rs b/client/encointer-api-client-extension/src/ceremonies.rs index 64e9a7b3..d3018c14 100644 --- a/client/encointer-api-client-extension/src/ceremonies.rs +++ b/client/encointer-api-client-extension/src/ceremonies.rs @@ -2,6 +2,7 @@ use crate::{Api, CommunitiesApi, Result, SchedulerApi}; use encointer_ceremonies_assignment::{ assignment_fn_inverse, meetup_index, meetup_location, meetup_time, }; +use encointer_node_notee_runtime::Hash; use encointer_primitives::{ ceremonies::{ Assignment, AssignmentCount, CommunityCeremony, MeetupIndexType, MeetupTimeOffsetType, @@ -14,6 +15,7 @@ use log::warn; use serde::{Deserialize, Serialize}; use sp_runtime::AccountId32 as AccountId; use substrate_api_client::{api::error::Error as ApiClientError, GetStorage}; + pub type Moment = u64; pub const ENCOINTER_CEREMONIES: &str = "EncointerCeremonies"; @@ -23,91 +25,120 @@ pub const ONE_DAY: Moment = 86_400_000; #[maybe_async::maybe_async(?Send)] pub trait CeremoniesApi { - async fn get_assignments(&self, community_ceremony: &CommunityCeremony) -> Result; + async fn get_assignments( + &self, + community_ceremony: &CommunityCeremony, + maybe_at: Option, + ) -> Result; async fn get_assignment_counts( &self, community_ceremony: &CommunityCeremony, + maybe_at: Option, ) -> Result; async fn get_bootstrapper( &self, community_ceremony: &CommunityCeremony, p: &ParticipantIndexType, + maybe_at: Option, ) -> Result>; async fn get_reputable( &self, community_ceremony: &CommunityCeremony, p: &ParticipantIndexType, + maybe_at: Option, ) -> Result>; async fn get_endorsee( &self, community_ceremony: &CommunityCeremony, p: &ParticipantIndexType, + maybe_at: Option, ) -> Result>; async fn get_newbie( &self, community_ceremony: &CommunityCeremony, p: &ParticipantIndexType, + maybe_at: Option, ) -> Result>; async fn get_registration( &self, community_ceremony: &CommunityCeremony, account_id: &AccountId, + maybe_at: Option, ) -> Result; async fn get_meetup_count( &self, community_ceremony: &CommunityCeremony, + maybe_at: Option, ) -> Result; async fn get_meetup_index( &self, community_ceremony: &CommunityCeremony, account_id: &AccountId, + maybe_at: Option, ) -> Result>; async fn get_meetup_location( &self, community_ceremony: &CommunityCeremony, meetup_index: MeetupIndexType, + maybe_at: Option, ) -> Result>; async fn get_meetup_participants( &self, community_ceremony: &CommunityCeremony, meetup_index: MeetupIndexType, + maybe_at: Option, ) -> Result>; - async fn get_meetup_time_offset(&self) -> Result>; + async fn get_meetup_time_offset( + &self, + maybe_at: Option, + ) -> Result>; - async fn get_meetup_time(&self, location: Location, one_day: Moment) -> Result; + async fn get_meetup_time( + &self, + location: Location, + one_day: Moment, + maybe_at: Option, + ) -> Result; async fn get_community_ceremony_stats( &self, community_ceremony: CommunityCeremony, + maybe_at: Option, ) -> Result; async fn get_attestees( &self, community_ceremony: CommunityCeremony, participant_index: ParticipantIndexType, + maybe_at: Option, ) -> Result>; async fn get_meetup_participant_count_vote( &self, community_ceremony: CommunityCeremony, account_id: AccountId, + maybe_at: Option, ) -> Result; } #[maybe_async::maybe_async(?Send)] impl CeremoniesApi for Api { - async fn get_assignments(&self, community_ceremony: &CommunityCeremony) -> Result { - self.get_storage_map(ENCOINTER_CEREMONIES, "Assignments", community_ceremony, None) + async fn get_assignments( + &self, + community_ceremony: &CommunityCeremony, + maybe_at: Option, + ) -> Result { + self.get_storage_map(ENCOINTER_CEREMONIES, "Assignments", community_ceremony, maybe_at) .await? .ok_or_else(|| ApiClientError::Other("Assignments don't exist".into())) } @@ -115,8 +146,9 @@ impl CeremoniesApi for Api { async fn get_assignment_counts( &self, community_ceremony: &CommunityCeremony, + maybe_at: Option, ) -> Result { - self.get_storage_map(ENCOINTER_CEREMONIES, "AssignmentCounts", community_ceremony, None) + self.get_storage_map(ENCOINTER_CEREMONIES, "AssignmentCounts", community_ceremony, maybe_at) .await? .ok_or_else(|| ApiClientError::Other("AssignmentCounts not found".into())) } @@ -125,13 +157,14 @@ impl CeremoniesApi for Api { &self, community_ceremony: &CommunityCeremony, p: &ParticipantIndexType, + maybe_at: Option, ) -> Result> { self.get_storage_double_map( ENCOINTER_CEREMONIES, "BootstrapperRegistry", community_ceremony, p, - None, + maybe_at, ) .await } @@ -140,13 +173,14 @@ impl CeremoniesApi for Api { &self, community_ceremony: &CommunityCeremony, p: &ParticipantIndexType, + maybe_at: Option, ) -> Result> { self.get_storage_double_map( ENCOINTER_CEREMONIES, "ReputableRegistry", community_ceremony, p, - None, + maybe_at, ) .await } @@ -155,13 +189,14 @@ impl CeremoniesApi for Api { &self, community_ceremony: &CommunityCeremony, p: &ParticipantIndexType, + maybe_at: Option, ) -> Result> { self.get_storage_double_map( ENCOINTER_CEREMONIES, "EndorseeRegistry", community_ceremony, p, - None, + maybe_at, ) .await } @@ -170,13 +205,14 @@ impl CeremoniesApi for Api { &self, community_ceremony: &CommunityCeremony, p: &ParticipantIndexType, + maybe_at: Option, ) -> Result> { self.get_storage_double_map( ENCOINTER_CEREMONIES, "NewbieRegistry", community_ceremony, p, - None, + maybe_at, ) .await } @@ -185,6 +221,7 @@ impl CeremoniesApi for Api { &self, community_ceremony: &CommunityCeremony, account_id: &AccountId, + maybe_at: Option, ) -> Result { let index_query = |storage_key| async move { self.get_storage_double_map( @@ -192,7 +229,7 @@ impl CeremoniesApi for Api { storage_key, community_ceremony, account_id, - None, + maybe_at, ) .await }; @@ -215,9 +252,10 @@ impl CeremoniesApi for Api { async fn get_meetup_count( &self, community_ceremony: &CommunityCeremony, + maybe_at: Option, ) -> Result { Ok(self - .get_storage_map(ENCOINTER_CEREMONIES, "MeetupCount", community_ceremony, None) + .get_storage_map(ENCOINTER_CEREMONIES, "MeetupCount", community_ceremony, maybe_at) .await? .unwrap_or(0)) } @@ -226,24 +264,25 @@ impl CeremoniesApi for Api { &self, community_ceremony: &CommunityCeremony, account_id: &AccountId, + maybe_at: Option, ) -> Result> { - let meetup_count = self.get_meetup_count(community_ceremony).await?; + let meetup_count = self.get_meetup_count(community_ceremony, maybe_at).await?; if meetup_count == 0 { warn!("Meetup Count is 0."); return Ok(None) } - let assignments = self.get_assignments(community_ceremony).await?; + let assignments = self.get_assignments(community_ceremony, maybe_at).await?; // Some helper queries to make below code more readable. let bootstrapper_count = || async { Ok::( - self.get_assignment_counts(community_ceremony).await?.bootstrappers, + self.get_assignment_counts(community_ceremony, maybe_at).await?.bootstrappers, ) }; - let registration = self.get_registration(community_ceremony, account_id).await?; + let registration = self.get_registration(community_ceremony, account_id, maybe_at).await?; let meetup_index_fn = |p_index, assignment_params| meetup_index(p_index, assignment_params, meetup_count); @@ -268,9 +307,11 @@ impl CeremoniesApi for Api { &self, community_ceremony: &CommunityCeremony, meetup_index: MeetupIndexType, + maybe_at: Option, ) -> Result> { let locations = self.get_locations(community_ceremony.0).await?; - let location_assignment_params = self.get_assignments(community_ceremony).await?.locations; + let location_assignment_params = + self.get_assignments(community_ceremony, maybe_at).await?.locations; Ok(meetup_location(meetup_index, locations, location_assignment_params)) } @@ -279,9 +320,10 @@ impl CeremoniesApi for Api { &self, community_ceremony: &CommunityCeremony, meetup_index: MeetupIndexType, + maybe_at: Option, ) -> Result> { let meetup_index_zero_based = meetup_index - 1; - let meetup_count = self.get_meetup_count(community_ceremony).await?; + let meetup_count = self.get_meetup_count(community_ceremony, maybe_at).await?; if meetup_index_zero_based > meetup_count { return Err(ApiClientError::Other( @@ -292,8 +334,8 @@ impl CeremoniesApi for Api { )) } - let params = self.get_assignments(community_ceremony).await?; - let assigned = self.get_assignment_counts(community_ceremony).await?; + let params = self.get_assignments(community_ceremony, maybe_at).await?; + let assigned = self.get_assignment_counts(community_ceremony, maybe_at).await?; let bootstrappers_reputables = stream::iter( assignment_fn_inverse( @@ -305,7 +347,7 @@ impl CeremoniesApi for Api { .unwrap_or_default(), ) .filter_map(|p_index| async move { - get_bootstrapper_or_reputable(self, community_ceremony, p_index, &assigned) + get_bootstrapper_or_reputable(self, community_ceremony, p_index, &assigned, maybe_at) .await .ok() .flatten() @@ -323,7 +365,7 @@ impl CeremoniesApi for Api { .filter(|p| p < &assigned.endorsees), ) .filter_map(|p| async move { - self.get_endorsee(community_ceremony, &(p + 1)).await.ok().flatten() + self.get_endorsee(community_ceremony, &(p + 1), maybe_at).await.ok().flatten() }); let newbies = stream::iter( @@ -338,19 +380,27 @@ impl CeremoniesApi for Api { .filter(|p| p < &assigned.newbies), ) .filter_map(|p| async move { - self.get_newbie(community_ceremony, &(p + 1)).await.ok().flatten() + self.get_newbie(community_ceremony, &(p + 1), maybe_at).await.ok().flatten() }); Ok(bootstrappers_reputables.chain(endorsees).chain(newbies).collect().await) } - async fn get_meetup_time_offset(&self) -> Result> { - self.get_storage(ENCOINTER_CEREMONIES, "MeetupTimeOffset", None).await + async fn get_meetup_time_offset( + &self, + maybe_at: Option, + ) -> Result> { + self.get_storage(ENCOINTER_CEREMONIES, "MeetupTimeOffset", maybe_at).await } - async fn get_meetup_time(&self, location: Location, one_day: Moment) -> Result { - let attesting_start = self.get_start_of_attesting_phase().await?; - let offset = self.get_meetup_time_offset().await?.unwrap_or(0); + async fn get_meetup_time( + &self, + location: Location, + one_day: Moment, + maybe_at: Option, + ) -> Result { + let attesting_start = self.get_start_of_attesting_phase(maybe_at).await?; + let offset = self.get_meetup_time_offset(maybe_at).await?.unwrap_or(0); Ok(meetup_time(location, attesting_start, one_day, offset)) } @@ -358,23 +408,26 @@ impl CeremoniesApi for Api { async fn get_community_ceremony_stats( &self, community_ceremony: CommunityCeremony, + maybe_at: Option, ) -> Result { - let assignment = self.get_assignments(&community_ceremony).await?; - let assignment_count = self.get_assignment_counts(&community_ceremony).await?; - let mcount = self.get_meetup_count(&community_ceremony).await?; + let assignment = self.get_assignments(&community_ceremony, maybe_at).await?; + let assignment_count = self.get_assignment_counts(&community_ceremony, maybe_at).await?; + let mcount = self.get_meetup_count(&community_ceremony, maybe_at).await?; let mut meetups = vec![]; // get stats of every meetup for m in 1..=mcount { - let m_location = self.get_meetup_location(&community_ceremony, m).await?.unwrap(); - let time = self.get_meetup_time(m_location, ONE_DAY).await.unwrap_or(0); - let participants = self.get_meetup_participants(&community_ceremony, m).await?; + let m_location = + self.get_meetup_location(&community_ceremony, m, maybe_at).await?.unwrap(); + let time = self.get_meetup_time(m_location, ONE_DAY, maybe_at).await.unwrap_or(0); + let participants = + self.get_meetup_participants(&community_ceremony, m, maybe_at).await?; let mut registrations = vec![]; for p in participants.into_iter() { - let r = self.get_registration(&community_ceremony, &p).await?; + let r = self.get_registration(&community_ceremony, &p, maybe_at).await?; registrations.push((p, r)) } @@ -394,13 +447,14 @@ impl CeremoniesApi for Api { &self, community_ceremony: CommunityCeremony, p_index: ParticipantIndexType, + maybe_at: Option, ) -> Result> { self.get_storage_double_map( "EncointerCeremonies", "AttestationRegistry", community_ceremony, p_index, - None, + maybe_at, ) .await? .ok_or_else(|| ApiClientError::Other("Attestees don't exist".into())) @@ -410,13 +464,14 @@ impl CeremoniesApi for Api { &self, community_ceremony: CommunityCeremony, account_id: AccountId, + maybe_at: Option, ) -> Result { self.get_storage_double_map( "EncointerCeremonies", "MeetupParticipantCountVote", community_ceremony, account_id, - None, + maybe_at, ) .await? .ok_or_else(|| ApiClientError::Other("MeetupParticipantCountVote don't exist".into())) @@ -428,12 +483,13 @@ async fn get_bootstrapper_or_reputable( community_ceremony: &CommunityCeremony, p_index: ParticipantIndexType, assigned: &AssignmentCount, + maybe_at: Option, ) -> Result> { if p_index < assigned.bootstrappers { - return api.get_bootstrapper(community_ceremony, &(p_index + 1)).await + return api.get_bootstrapper(community_ceremony, &(p_index + 1), maybe_at).await } else if p_index < assigned.bootstrappers + assigned.reputables { return api - .get_reputable(community_ceremony, &(p_index - assigned.bootstrappers + 1)) + .get_reputable(community_ceremony, &(p_index - assigned.bootstrappers + 1), maybe_at) .await } diff --git a/client/encointer-api-client-extension/src/scheduler.rs b/client/encointer-api-client-extension/src/scheduler.rs index 442c443e..da112760 100644 --- a/client/encointer-api-client-extension/src/scheduler.rs +++ b/client/encointer-api-client-extension/src/scheduler.rs @@ -1,42 +1,51 @@ use crate::{Api, Moment, Result}; +use encointer_node_notee_runtime::Hash; use encointer_primitives::scheduler::CeremonyPhaseType; use substrate_api_client::{api::error::Error as ApiClientError, GetStorage}; #[maybe_async::maybe_async(?Send)] pub trait SchedulerApi { - async fn get_current_phase(&self) -> Result; - async fn get_next_phase_timestamp(&self) -> Result; - async fn get_phase_duration(&self, phase: CeremonyPhaseType) -> Result; - async fn get_start_of_attesting_phase(&self) -> Result; + async fn get_current_phase(&self, maybe_at: Option) -> Result; + async fn get_next_phase_timestamp(&self, maybe_at: Option) -> Result; + async fn get_phase_duration( + &self, + phase: CeremonyPhaseType, + maybe_at: Option, + ) -> Result; + async fn get_start_of_attesting_phase(&self, maybe_at: Option) -> Result; } #[maybe_async::maybe_async(?Send)] impl SchedulerApi for Api { - async fn get_current_phase(&self) -> Result { - self.get_storage("EncointerScheduler", "CurrentPhase", None) + async fn get_current_phase(&self, maybe_at: Option) -> Result { + self.get_storage("EncointerScheduler", "CurrentPhase", maybe_at) .await? .ok_or_else(|| ApiClientError::Other("Couldn't get CurrentPhase".into())) } - async fn get_next_phase_timestamp(&self) -> Result { - self.get_storage("EncointerScheduler", "NextPhaseTimestamp", None) + async fn get_next_phase_timestamp(&self, maybe_at: Option) -> Result { + self.get_storage("EncointerScheduler", "NextPhaseTimestamp", maybe_at) .await? .ok_or_else(|| ApiClientError::Other("Couldn't get NextPhaseTimestamp".into())) } - async fn get_phase_duration(&self, phase: CeremonyPhaseType) -> Result { - self.get_storage_map("EncointerScheduler", "PhaseDurations", phase, None) + async fn get_phase_duration( + &self, + phase: CeremonyPhaseType, + maybe_at: Option, + ) -> Result { + self.get_storage_map("EncointerScheduler", "PhaseDurations", phase, maybe_at) .await? .ok_or_else(|| ApiClientError::Other("Couldn't get PhaseDuration".into())) } - async fn get_start_of_attesting_phase(&self) -> Result { - let next_phase_timestamp = self.get_next_phase_timestamp().await?; + async fn get_start_of_attesting_phase(&self, maybe_at: Option) -> Result { + let next_phase_timestamp = self.get_next_phase_timestamp(maybe_at).await?; - match self.get_current_phase().await? { + match self.get_current_phase(maybe_at).await? { CeremonyPhaseType::Assigning => Ok(next_phase_timestamp), // - next_phase_timestamp.rem(ONE_DAY), CeremonyPhaseType::Attesting => { - self.get_phase_duration(CeremonyPhaseType::Attesting) + self.get_phase_duration(CeremonyPhaseType::Attesting, maybe_at) .await .map(|dur| next_phase_timestamp - dur) //- next_phase_timestamp.rem(ONE_DAY) }, diff --git a/client/py_client/client.py b/client/py_client/client.py index ef7769b8..d043172a 100644 --- a/client/py_client/client.py +++ b/client/py_client/client.py @@ -178,7 +178,7 @@ def list_meetups(self, cid): participants = [] while len(lines) > 0: l = lines.pop(0) - if ('MeetupRegistry' in l) or ('total' in l): + if ('MeetupRegistry' in l) or ('total' in l) or ('CSV:' in l): break participants.append(l.strip()) meetups.append(participants) @@ -257,37 +257,37 @@ def purge_community_ceremony(self, cid, from_cindex, to_cindex, pay_fees_in_cc=F def create_faucet(self, account, facuet_name, amount, drip_amount, whitelist, cid=None, pay_fees_in_cc=False): ret = self.run_cli_command(["create-faucet", account, facuet_name, str(amount), str(drip_amount)] + whitelist, cid, pay_fees_in_cc) return ret.stdout.decode("utf-8").strip() - + def drip_faucet(self, account, facuet_account, cindex, cid=None, pay_fees_in_cc=False): ret = self.run_cli_command(["drip-faucet", account, facuet_account, str(cindex)], cid, pay_fees_in_cc) return ret.stdout.decode("utf-8").strip() - + def dissolve_faucet(self, account, facuet_account, beneficiary, cid=None, pay_fees_in_cc=False): ret = self.run_cli_command(["dissolve-faucet", "--signer", account, facuet_account, beneficiary], cid, pay_fees_in_cc) return ret.stdout.decode("utf-8").strip() - + def close_faucet(self, account, facuet_account, cid=None, pay_fees_in_cc=False): ret = self.run_cli_command(["close-faucet", account, facuet_account], cid, pay_fees_in_cc) return ret.stdout.decode("utf-8").strip() - + def set_faucet_reserve_amount(self, account, amount, cid=None, pay_fees_in_cc=False): ret = self.run_cli_command(["set-faucet-reserve-amount", "--signer", account, str(amount)], cid, pay_fees_in_cc) return ret.stdout.decode("utf-8").strip() - + def submit_set_inactivity_timeout_proposal(self, account, inactivity_timeout, cid=None, pay_fees_in_cc=False): ret = self.run_cli_command(["submit-set-inactivity-timeout-proposal", account, str(inactivity_timeout)], cid, pay_fees_in_cc) return ret.stdout.decode("utf-8").strip() - + def vote(self, account, proposal_id, vote, reputations, cid=None, pay_fees_in_cc=False): reputations = [f'{cid}_{cindex}' for [cid,cindex] in reputations] reputation_vec = ','.join(reputations) ret = self.run_cli_command(["vote", account, str(proposal_id), vote, reputation_vec], cid, pay_fees_in_cc) return ret.stdout.decode("utf-8").strip() - + def update_proposal_state(self, account, proposal_id, cid=None, pay_fees_in_cc=False): ret = self.run_cli_command(["update-proposal-state", account, str(proposal_id)], cid, pay_fees_in_cc) return ret.stdout.decode("utf-8").strip() - + def list_proposals(self): ret = self.run_cli_command(["list-proposals"]) - return ret.stdout.decode("utf-8").strip() \ No newline at end of file + return ret.stdout.decode("utf-8").strip() diff --git a/client/src/commands/encointer_ceremonies.rs b/client/src/commands/encointer_ceremonies.rs index 749f54f9..9613954d 100644 --- a/client/src/commands/encointer_ceremonies.rs +++ b/client/src/commands/encointer_ceremonies.rs @@ -1,7 +1,7 @@ use crate::{ cli_args::EncointerArgsExtractor, commands::{ - encointer_communities::get_cid_names, + encointer_communities::get_community_identifiers, encointer_core::{set_api_extrisic_params_builder, verify_cid}, encointer_scheduler::get_ceremony_index, }, @@ -15,19 +15,20 @@ use crate::{ }; use clap::ArgMatches; use encointer_api_client_extension::{ - Api, ApiClientError, CeremoniesApi, EncointerXt, ParentchainExtrinsicSigner, SchedulerApi, - ENCOINTER_CEREMONIES, + Api, ApiClientError, AttestationState, CeremoniesApi, EncointerXt, ParentchainExtrinsicSigner, + SchedulerApi, ENCOINTER_CEREMONIES, }; use encointer_node_notee_runtime::{AccountId, Hash, Moment, Signature, ONE_DAY}; use encointer_primitives::{ ceremonies::{ - CeremonyIndexType, ClaimOfAttendance, CommunityCeremony, CommunityReputation, - MeetupIndexType, ParticipantIndexType, ProofOfAttendance, Reputation, + AttestationIndexType, CeremonyIndexType, ClaimOfAttendance, CommunityCeremony, + CommunityReputation, MeetupIndexType, ParticipantIndexType, ProofOfAttendance, Reputation, ReputationLifetimeType, }, communities::CommunityIdentifier, scheduler::CeremonyPhaseType, }; +use itertools::Itertools; use log::{debug, error, info}; use parity_scale_codec::{Decode, Encode}; use sp_application_crypto::sr25519; @@ -46,9 +47,11 @@ pub fn list_participants(_args: &str, matches: &ArgMatches<'_>) -> Result<(), cl let rt = tokio::runtime::Runtime::new().unwrap(); rt.block_on(async { let api = get_chain_api(matches).await; + let maybe_at = matches.at_block_arg(); let cid = - verify_cid(&api, matches.cid_arg().expect("please supply argument --cid"), None).await; - let current_ceremony_index = get_ceremony_index(&api, None).await; + verify_cid(&api, matches.cid_arg().expect("please supply argument --cid"), maybe_at) + .await; + let current_ceremony_index = get_ceremony_index(&api, maybe_at).await; let cindex = matches.ceremony_index_arg().map_or_else( || current_ceremony_index, @@ -67,7 +70,7 @@ pub fn list_participants(_args: &str, matches: &ArgMatches<'_>) -> Result<(), cl println!("Querying {}", registries[i]); let count: ParticipantIndexType = api - .get_storage_map(ENCOINTER_CEREMONIES, counts[i], (cid, cindex), None) + .get_storage_map(ENCOINTER_CEREMONIES, counts[i], (cid, cindex), maybe_at) .await .unwrap() .unwrap_or(0); @@ -80,7 +83,7 @@ pub fn list_participants(_args: &str, matches: &ArgMatches<'_>) -> Result<(), cl registries[i], (cid, cindex), p_index, - None, + maybe_at, ) .await .unwrap() @@ -88,6 +91,10 @@ pub fn list_participants(_args: &str, matches: &ArgMatches<'_>) -> Result<(), cl println!("{}[{}, {}] = {}", registries[i], cindex, p_index, accountid); } } + println!( + "CSV: {cindex}, {cid}, {}, {}, {}, {}", + num_participants[0], num_participants[1], num_participants[2], num_participants[3] + ); println!("total: {} guaranteed seats + {} newbies = {} total participants who would like to attend", num_participants[0..=2].iter().sum::(), num_participants[3], @@ -101,9 +108,11 @@ pub fn list_meetups(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap::E let rt = tokio::runtime::Runtime::new().unwrap(); rt.block_on(async { let api = get_chain_api(matches).await; + let maybe_at = matches.at_block_arg(); let cid = - verify_cid(&api, matches.cid_arg().expect("please supply argument --cid"), None).await; - let current_ceremony_index = get_ceremony_index(&api, None).await; + verify_cid(&api, matches.cid_arg().expect("please supply argument --cid"), maybe_at) + .await; + let current_ceremony_index = get_ceremony_index(&api, maybe_at).await; let cindex = matches.ceremony_index_arg().map_or_else( || current_ceremony_index, @@ -114,7 +123,7 @@ pub fn list_meetups(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap::E println!("listing meetups for cid {cid} and ceremony nr {cindex}"); - let stats = api.get_community_ceremony_stats(community_ceremony).await.unwrap(); + let stats = api.get_community_ceremony_stats(community_ceremony, maybe_at).await.unwrap(); let mut num_assignees = 0u64; @@ -143,6 +152,7 @@ pub fn list_meetups(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap::E println!("MeetupRegistry[{:?}, {}] EMPTY", &community_ceremony, meetup.index); } } + println!("CSV: {cindex}, {cid}, {num_assignees}, {}", stats.meetups.len()); println!("total number of assignees: {num_assignees}"); Ok(()) }) @@ -153,9 +163,11 @@ pub fn print_ceremony_stats(_args: &str, matches: &ArgMatches<'_>) -> Result<(), let rt = tokio::runtime::Runtime::new().unwrap(); rt.block_on(async { let api = get_chain_api(matches).await; + let maybe_at = matches.at_block_arg(); let cid = - verify_cid(&api, matches.cid_arg().expect("please supply argument --cid"), None).await; - let current_ceremony_index = get_ceremony_index(&api, None).await; + verify_cid(&api, matches.cid_arg().expect("please supply argument --cid"), maybe_at) + .await; + let current_ceremony_index = get_ceremony_index(&api, maybe_at).await; let cindex = matches.ceremony_index_arg().map_or_else( || current_ceremony_index, @@ -164,7 +176,7 @@ pub fn print_ceremony_stats(_args: &str, matches: &ArgMatches<'_>) -> Result<(), let community_ceremony = (cid, cindex); - let stats = api.get_community_ceremony_stats(community_ceremony).await.unwrap(); + let stats = api.get_community_ceremony_stats(community_ceremony, maybe_at).await.unwrap(); // serialization prints the the account id better than `debug` println!("{}", serde_json::to_string_pretty(&stats).unwrap()); @@ -176,21 +188,145 @@ pub fn list_attestees(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap: let rt = tokio::runtime::Runtime::new().unwrap(); rt.block_on(async { let api = get_chain_api(matches).await; + let maybe_at = matches.at_block_arg(); let cid = - verify_cid(&api, matches.cid_arg().expect("please supply argument --cid"), None).await; - let current_ceremony_index = get_ceremony_index(&api, None).await; + verify_cid(&api, matches.cid_arg().expect("please supply argument --cid"), maybe_at) + .await; + + let current_ceremony_index = get_ceremony_index(&api, maybe_at).await; let cindex = matches.ceremony_index_arg().map_or_else( || current_ceremony_index, |ci| into_effective_cindex(ci, current_ceremony_index), ); - let community_ceremony = (cid, cindex); + println!("listing attestees for cid {cid} and ceremony nr {cindex}"); - let stats = api.get_community_ceremony_stats(community_ceremony).await.unwrap(); + let wcount = get_attestee_count(&api, (cid, cindex), maybe_at).await; + println!("number of attestees: {wcount}"); - // serialization prints the the account id better than `debug` - println!("{}", serde_json::to_string_pretty(&stats).unwrap()); + println!("listing participants for cid {cid} and ceremony nr {cindex}"); + + let counts = vec!["BootstrapperCount", "ReputableCount", "EndorseeCount", "NewbieCount"]; + let count_query = |count_index| { + let api_local = api.clone(); + let counts_local = counts.clone(); + async move { + api_local + .get_storage_map( + ENCOINTER_CEREMONIES, + counts_local[count_index], + (cid, cindex), + maybe_at, + ) + .await + } + }; + + let registries = + vec!["BootstrapperRegistry", "ReputableRegistry", "EndorseeRegistry", "NewbieRegistry"]; + let account_query = |registry_index, p_index| { + let api_local = api.clone(); + let registries_local = registries.clone(); + async move { + api_local + .get_storage_double_map( + ENCOINTER_CEREMONIES, + registries_local[registry_index], + (cid, cindex), + p_index, + maybe_at, + ) + .await + } + }; + + let mut participants_windex = HashMap::new(); + + for (i, item) in registries.iter().enumerate() { + println!("Querying {item}"); + + let count: ParticipantIndexType = count_query(i).await.unwrap().unwrap_or(0); + println!("number of participants assigned: {count}"); + + for p_index in 1..count + 1 { + let accountid: AccountId = account_query(i, p_index).await.unwrap().unwrap(); + + match get_participant_attestation_index(&api, (cid, cindex), &accountid, maybe_at) + .await + { + Some(windex) => + participants_windex.insert(windex as AttestationIndexType, accountid), + _ => continue, + }; + } + } + + let mut attestation_states = Vec::with_capacity(wcount as usize); + + for w in 1..wcount + 1 { + let attestor = participants_windex[&w].clone(); + let meetup_index = api + .get_meetup_index(&(cid, cindex), &attestor, maybe_at) + .await + .unwrap() + .unwrap(); + let attestees = api.get_attestees((cid, cindex), w, maybe_at).await.unwrap(); + let vote = api + .get_meetup_participant_count_vote((cid, cindex), attestor.clone(), maybe_at) + .await + .unwrap_or(0); + let attestation_state = + AttestationState::new((cid, cindex), meetup_index, vote, w, attestor, attestees); + + attestation_states.push(attestation_state); + } + + // Group attestation states by meetup index + attestation_states.sort_by(|a, b| a.meetup_index.partial_cmp(&b.meetup_index).unwrap()); + + for a in attestation_states.iter() { + println!("{a:?}"); + } + + let mut meetup_sizes: HashMap = HashMap::new(); + let _: Vec<_> = api + .get_community_ceremony_stats((cid, cindex), maybe_at) + .await + .unwrap() + .meetups + .iter() + .map(|m| meetup_sizes.insert(m.index, m.registrations.len())) + .collect(); + + let mut all_votes: HashMap = HashMap::new(); + for m in meetup_sizes.keys().sorted() { + let mut votes: Vec = Vec::with_capacity(32); + for a in attestation_states.iter() { + if a.meetup_index == *m { + votes.push(a.vote); + } + } + let mut mean_vote: f64 = votes.iter().sum::() as f64 / votes.len() as f64; + if mean_vote.is_nan() { + mean_vote = 0f64; + } + + all_votes.insert(*m, mean_vote); + println!( + "CSVmeetupVotes: {cindex}, {cid}, {m}, {}, {:.3}, {:?}", + meetup_sizes.get(m).unwrap(), + mean_vote, + votes.iter().map(|x| x.to_string()).collect::>().join(";") + ); + } + + println!("cindex, cid, assignees, attestors, sum of mean votes"); + println!( + "CSV: {cindex}, {cid}, {}, {wcount}, {}", + meetup_sizes.values().sum::(), + all_votes.values().sum::() + ); Ok(()) }) .into() @@ -201,16 +337,16 @@ pub fn list_reputables(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap let api = get_chain_api(matches).await; let is_verbose = matches.verbose_flag(); - let at_block = matches.at_block_arg(); + let maybe_at = matches.at_block_arg(); - let lifetime = get_reputation_lifetime(&api, at_block).await; - let current_ceremony_index = get_ceremony_index(&api, at_block).await; + let lifetime = get_reputation_lifetime(&api, maybe_at).await; + let current_ceremony_index = get_ceremony_index(&api, maybe_at).await; let first_ceremony_index_of_interest = current_ceremony_index.saturating_sub(lifetime); let ceremony_indices: Vec = (first_ceremony_index_of_interest..current_ceremony_index).collect(); - let community_ids = get_cid_names(&api).await.unwrap().into_iter().map(|names| names.cid); + let community_ids = get_community_identifiers(&api, maybe_at).await.expect("no communities found"); let mut reputables_csv = Vec::new(); @@ -219,7 +355,7 @@ pub fn list_reputables(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap println!("Community ID: {community_id:?}"); let mut reputables: HashMap = HashMap::new(); for ceremony_index in &ceremony_indices { - let (attendees, noshows) = get_attendees_for_community_ceremony(&api, (community_id, *ceremony_index), at_block).await; + let (attendees, noshows) = get_attendees_for_community_ceremony(&api, (community_id, *ceremony_index), maybe_at).await; println!("Cycle ID {ceremony_index:?}: Total attested attendees: {:} (noshows: {:})", attendees.len(), noshows.len()); for attendee in attendees { reputables_csv.push(format!("{community_id:?},{ceremony_index:?},{}", attendee.to_ss58check())); @@ -253,7 +389,7 @@ pub fn upgrade_registration(_args: &str, matches: &ArgMatches<'_>) -> Result<(), let cid = verify_cid(&api, matches.cid_arg().expect("please supply argument --cid"), None).await; - let current_phase = api.get_current_phase().await.unwrap(); + let current_phase = api.get_current_phase(None).await.unwrap(); if !(current_phase == CeremonyPhaseType::Registering || current_phase == CeremonyPhaseType::Attesting) { @@ -264,7 +400,7 @@ pub fn upgrade_registration(_args: &str, matches: &ArgMatches<'_>) -> Result<(), if current_phase == CeremonyPhaseType::Registering { reputation_cindex -= 1; } - let rep = get_reputation(&api, &accountid, cid, reputation_cindex).await; + let rep = get_reputation(&api, &accountid, cid, reputation_cindex, None).await; info!("{} has reputation {:?}", accountid, rep); let proof = match rep { Reputation::VerifiedUnlinked => @@ -307,7 +443,7 @@ pub fn register_participant(_args: &str, matches: &ArgMatches<'_>) -> Result<(), let cindex = get_ceremony_index(&api, None).await; let cid = verify_cid(&api, matches.cid_arg().expect("please supply argument --cid"), None).await; - let rep = get_reputation(&api, &accountid, cid, cindex - 1).await; + let rep = get_reputation(&api, &accountid, cid, cindex - 1, None).await; info!("{} has reputation {:?}", accountid, rep); let proof = match rep { Reputation::Unverified => None, @@ -318,7 +454,7 @@ pub fn register_participant(_args: &str, matches: &ArgMatches<'_>) -> Result<(), Some(prove_attendance(accountid, cid, cindex - 1, arg_who)), }; debug!("proof: {:x?}", proof.encode()); - let current_phase = api.get_current_phase().await.unwrap(); + let current_phase = api.get_current_phase(None).await.unwrap(); if !(current_phase == CeremonyPhaseType::Registering || current_phase == CeremonyPhaseType::Attesting) { @@ -366,7 +502,7 @@ pub fn unregister_participant(_args: &str, matches: &ArgMatches<'_>) -> Result<( None => None, }; - let current_phase = api.get_current_phase().await.unwrap(); + let current_phase = api.get_current_phase(None).await.unwrap(); if !(current_phase == CeremonyPhaseType::Registering || current_phase == CeremonyPhaseType::Attesting) { @@ -537,7 +673,7 @@ pub fn claim_reward(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap::E if matches.all_flag() { let mut cindex = get_ceremony_index(&api, None).await; - if api.get_current_phase().await.unwrap() == CeremonyPhaseType::Registering { + if api.get_current_phase(None).await.unwrap() == CeremonyPhaseType::Registering { cindex -= 1; } let meetup_count = api @@ -724,13 +860,14 @@ async fn get_reputation( prover: &AccountId, cid: CommunityIdentifier, cindex: CeremonyIndexType, + maybe_at: Option, ) -> Reputation { api.get_storage_double_map( "EncointerCeremonies", "ParticipantReputation", (cid, cindex), prover.clone(), - None, + maybe_at, ) .await .unwrap() @@ -750,7 +887,7 @@ async fn get_reputation_history( async fn get_attendees_for_community_ceremony( api: &Api, community_ceremony: CommunityCeremony, - at_block: Option, + maybe_at: Option, ) -> (Vec, Vec) { let key_prefix = api .get_storage_double_map_key_prefix( @@ -762,7 +899,7 @@ async fn get_attendees_for_community_ceremony( .unwrap(); let max_keys = 1000; let storage_keys = api - .get_storage_keys_paged(Some(key_prefix), max_keys, None, at_block) + .get_storage_keys_paged(Some(key_prefix), max_keys, None, maybe_at) .await .unwrap(); @@ -772,7 +909,13 @@ async fn get_attendees_for_community_ceremony( let mut attendees = Vec::new(); let mut noshows = Vec::new(); for storage_key in storage_keys.iter() { - match api.get_storage_by_key(storage_key.clone(), at_block).await.unwrap().unwrap() { + match api + .get_storage_by_key(storage_key.clone(), maybe_at) + .await + // todo: back to simple unwarp() https://github.com/encointer/encointer-node/issues/364 + .unwrap_or(Some(Reputation::VerifiedLinked(0))) + .unwrap() + { Reputation::VerifiedUnlinked | Reputation::VerifiedLinked(_) => { let key_postfix = storage_key.as_ref(); attendees.push( @@ -790,8 +933,8 @@ async fn get_attendees_for_community_ceremony( (attendees, noshows) } -async fn get_reputation_lifetime(api: &Api, at_block: Option) -> ReputationLifetimeType { - api.get_storage("EncointerCeremonies", "ReputationLifetime", at_block) +async fn get_reputation_lifetime(api: &Api, maybe_at: Option) -> ReputationLifetimeType { + api.get_storage("EncointerCeremonies", "ReputationLifetime", maybe_at) .await .unwrap() .unwrap_or(5) @@ -805,14 +948,14 @@ async fn new_claim_for( ) -> Vec { let cindex = get_ceremony_index(api, None).await; let mindex = api - .get_meetup_index(&(cid, cindex), &claimant.public().into()) + .get_meetup_index(&(cid, cindex), &claimant.public().into(), None) .await .unwrap() .expect("participant must be assigned to meetup to generate a claim"); // implicitly assume that participant meet at the right place at the right time - let mloc = api.get_meetup_location(&(cid, cindex), mindex).await.unwrap().unwrap(); - let mtime = api.get_meetup_time(mloc, ONE_DAY).await.unwrap(); + let mloc = api.get_meetup_location(&(cid, cindex), mindex, None).await.unwrap().unwrap(); + let mtime = api.get_meetup_time(mloc, ONE_DAY, None).await.unwrap(); info!( "creating claim for {} at loc {} (lat: {} lon: {}) at time {}, cindex {}", @@ -921,3 +1064,25 @@ async fn get_bootstrappers_with_remaining_newbie_tickets( Ok(bs_with_tickets) } + +async fn get_attestee_count( + api: &Api, + key: CommunityCeremony, + maybe_at: Option, +) -> ParticipantIndexType { + api.get_storage_map("EncointerCeremonies", "AttestationCount", key, maybe_at) + .await + .unwrap() + .unwrap_or(0) +} + +async fn get_participant_attestation_index( + api: &Api, + key: CommunityCeremony, + accountid: &AccountId, + maybe_at: Option, +) -> Option { + api.get_storage_double_map("EncointerCeremonies", "AttestationIndex", key, accountid, maybe_at) + .await + .unwrap() +} diff --git a/client/src/commands/encointer_communities.rs b/client/src/commands/encointer_communities.rs index ccf3b84e..bcdc38cf 100644 --- a/client/src/commands/encointer_communities.rs +++ b/client/src/commands/encointer_communities.rs @@ -81,7 +81,7 @@ pub fn new_community(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap:: send_and_wait_for_in_block(&api, xt(&api, new_community_call).await, matches.tx_payment_cid_arg()).await; println!("{cid}"); - if api.get_current_phase().await.unwrap() != CeremonyPhaseType::Registering { + if api.get_current_phase(None).await.unwrap() != CeremonyPhaseType::Registering { error!("Wrong ceremony phase for registering new locations for {}", cid); error!("Aborting without registering additional locations"); std::process::exit(exit_code::WRONG_PHASE); @@ -144,7 +144,7 @@ pub fn add_locations(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap:: println!("0x{}", hex::encode(add_location_maybe_batch_call.encode())); } else { // ---- send xt's to chain - if api.get_current_phase().await.unwrap() != CeremonyPhaseType::Registering { + if api.get_current_phase(None).await.unwrap() != CeremonyPhaseType::Registering { error!("Wrong ceremony phase for registering new locations for {}", cid); error!("Aborting without registering additional locations"); std::process::exit(exit_code::WRONG_PHASE); diff --git a/client/src/commands/encointer_core.rs b/client/src/commands/encointer_core.rs index 594bcf6c..8cd3a13b 100644 --- a/client/src/commands/encointer_core.rs +++ b/client/src/commands/encointer_core.rs @@ -44,11 +44,14 @@ pub fn balance(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap::Error> println! {"{balance:?}"}; }, None => { + if maybe_at.is_some() { + panic!("can't apply --at if --cid not set") + }; if matches.all_flag() { let community_balances = get_all_balances(&api, &accountid).await.unwrap(); let bn = get_block_number(&api, maybe_at).await; for b in community_balances.iter() { - let dr = get_demurrage_per_block(&api, b.0).await; + let dr = get_demurrage_per_block(&api, b.0, maybe_at).await; println!("{}: {}", b.0, apply_demurrage(b.1, bn, dr)) } } @@ -196,7 +199,7 @@ pub async fn get_community_balance( ) -> BalanceType { let cid = verify_cid(api, cid_str, maybe_at).await; let bn = get_block_number(api, maybe_at).await; - let dr = get_demurrage_per_block(api, cid).await; + let dr = get_demurrage_per_block(api, cid, maybe_at).await; if let Some(entry) = api .get_storage_double_map("EncointerBalances", "Balance", cid, account_id, maybe_at) @@ -216,7 +219,7 @@ pub async fn get_community_issuance( ) -> BalanceType { let cid = verify_cid(api, cid_str, maybe_at).await; let bn = get_block_number(api, maybe_at).await; - let dr = get_demurrage_per_block(api, cid).await; + let dr = get_demurrage_per_block(api, cid, maybe_at).await; if let Some(entry) = api .get_storage_map("EncointerBalances", "TotalIssuance", cid, maybe_at) @@ -229,9 +232,13 @@ pub async fn get_community_issuance( } } -async fn get_demurrage_per_block(api: &Api, cid: CommunityIdentifier) -> Demurrage { +async fn get_demurrage_per_block( + api: &Api, + cid: CommunityIdentifier, + maybe_at: Option, +) -> Demurrage { let d: Option = api - .get_storage_map("EncointerBalances", "DemurragePerBlock", cid, None) + .get_storage_map("EncointerBalances", "DemurragePerBlock", cid, maybe_at) .await .unwrap(); diff --git a/client/src/commands/encointer_democracy.rs b/client/src/commands/encointer_democracy.rs index d5fa1949..3abeb05d 100644 --- a/client/src/commands/encointer_democracy.rs +++ b/client/src/commands/encointer_democracy.rs @@ -48,12 +48,12 @@ pub fn list_proposals(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap: let rt = tokio::runtime::Runtime::new().unwrap(); rt.block_on(async { let api = get_chain_api(matches).await; - let at_block = matches.at_block_arg(); + let maybe_at = matches.at_block_arg(); let key_prefix = api.get_storage_map_key_prefix("EncointerDemocracy", "Proposals").await.unwrap(); let max_keys = 1000; let storage_keys = api - .get_storage_keys_paged(Some(key_prefix), max_keys, None, at_block) + .get_storage_keys_paged(Some(key_prefix), max_keys, None, maybe_at) .await .unwrap(); if storage_keys.len() == max_keys as usize { @@ -66,7 +66,7 @@ pub fn list_proposals(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap: .unwrap(); println!("id: {}", proposal_id); let proposal: Proposal = - api.get_storage_by_key(storage_key.clone(), at_block).await.unwrap().unwrap(); + api.get_storage_by_key(storage_key.clone(), maybe_at).await.unwrap().unwrap(); println!("action: {:?}", proposal.action); println!("start block: {}", proposal.start); println!("start cindex: {}", proposal.start_cindex); diff --git a/client/src/commands/encointer_faucet.rs b/client/src/commands/encointer_faucet.rs index bdd93456..2ac6b2f7 100644 --- a/client/src/commands/encointer_faucet.rs +++ b/client/src/commands/encointer_faucet.rs @@ -257,14 +257,14 @@ pub fn list_faucets(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap::E let api = get_chain_api(matches).await; let is_verbose = matches.verbose_flag(); - let at_block = matches.at_block_arg(); + let maybe_at = matches.at_block_arg(); let key_prefix = api.get_storage_map_key_prefix("EncointerFaucet", "Faucets").await.unwrap(); let max_keys = 1000; let storage_keys = api - .get_storage_keys_paged(Some(key_prefix), max_keys, None, at_block) + .get_storage_keys_paged(Some(key_prefix), max_keys, None, maybe_at) .await .unwrap(); @@ -277,7 +277,7 @@ pub fn list_faucets(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap::E let faucet_address = AccountId::decode(&mut key_postfix[key_postfix.len() - 32..].as_ref()).unwrap(); let faucet: Faucet = - api.get_storage_by_key(storage_key.clone(), at_block).await.unwrap().unwrap(); + api.get_storage_by_key(storage_key.clone(), maybe_at).await.unwrap().unwrap(); if is_verbose { println!("address: {}", faucet_address.to_ss58check()); diff --git a/client/src/commands/encointer_scheduler.rs b/client/src/commands/encointer_scheduler.rs index a6570b35..26285d95 100644 --- a/client/src/commands/encointer_scheduler.rs +++ b/client/src/commands/encointer_scheduler.rs @@ -26,11 +26,11 @@ pub fn get_phase(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap::Erro debug!("block number: {}", bn); let cindex = get_ceremony_index(&api, None).await; info!("ceremony index: {}", cindex); - let tnext: Moment = api.get_next_phase_timestamp().await.unwrap(); + let tnext: Moment = api.get_next_phase_timestamp(None).await.unwrap(); debug!("next phase timestamp: {}", tnext); // <<<< - let phase = api.get_current_phase().await.unwrap(); + let phase = api.get_current_phase(None).await.unwrap(); println!("{phase:?}"); Ok(()) }) @@ -72,15 +72,15 @@ pub fn next_phase(_args: &str, matches: &ArgMatches<'_>) -> Result<(), clap::Err send_and_wait_for_in_block(&api, xt(&api, next_phase_call).await, tx_payment_cid_arg).await; - let phase = api.get_current_phase().await.unwrap(); + let phase = api.get_current_phase(None).await.unwrap(); println!("Phase is now: {phase:?}"); Ok(()) }) .into() } -pub async fn get_ceremony_index(api: &Api, at_block: Option) -> CeremonyIndexType { - api.get_storage("EncointerScheduler", "CurrentCeremonyIndex", at_block) +pub async fn get_ceremony_index(api: &Api, maybe_at: Option) -> CeremonyIndexType { + api.get_storage("EncointerScheduler", "CurrentCeremonyIndex", maybe_at) .await .unwrap() .unwrap() diff --git a/client/src/main.rs b/client/src/main.rs index 5a54137b..b228908d 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -232,6 +232,10 @@ fn main() { .add_cmd( Command::new("list-communities") .description("list all registered communities") + .options(|app| { + app.setting(AppSettings::ColoredHelp) + .at_block_arg() + }) .runner(commands::encointer_communities::list_communities), ) .add_cmd( @@ -261,8 +265,9 @@ fn main() { Command::new("list-participants") .description("list all registered participants supplied community identifier and ceremony index") .options(|app| { - app.setting(AppSettings::ColoredHelp) + app.setting(AppSettings::ColoredHelp).setting(AppSettings::AllowNegativeNumbers) .ceremony_index_arg() + .at_block_arg() }) .runner(commands::encointer_ceremonies::list_participants), ) @@ -270,8 +275,9 @@ fn main() { Command::new("list-meetups") .description("list all assigned meetups for supplied community identifier and ceremony index") .options(|app| { - app.setting(AppSettings::ColoredHelp) + app.setting(AppSettings::ColoredHelp).setting(AppSettings::AllowNegativeNumbers) .ceremony_index_arg() + .at_block_arg() }) .runner(commands::encointer_ceremonies::list_meetups), ) @@ -279,8 +285,9 @@ fn main() { Command::new("print-ceremony-stats") .description("pretty prints all information for a community ceremony") .options(|app| { - app.setting(AppSettings::ColoredHelp) + app.setting(AppSettings::ColoredHelp).setting(AppSettings::AllowNegativeNumbers) .ceremony_index_arg() + .at_block_arg() }) .runner(commands::encointer_ceremonies::print_ceremony_stats), ) @@ -288,8 +295,9 @@ fn main() { Command::new("list-attestees") .description("list all attestees for participants for supplied community identifier and ceremony index") .options(|app| { - app.setting(AppSettings::ColoredHelp) + app.setting(AppSettings::ColoredHelp).setting(AppSettings::AllowNegativeNumbers) .ceremony_index_arg() + .at_block_arg() }) .runner(commands::encointer_ceremonies::list_attestees), ) @@ -327,7 +335,7 @@ fn main() { Command::new("unregister-participant") .description("Unregister encointer ceremony participant for supplied community") .options(|app| { - app.setting(AppSettings::ColoredHelp) + app.setting(AppSettings::ColoredHelp).setting(AppSettings::AllowNegativeNumbers) .account_arg() .signer_arg("Account which signs the tx.") .ceremony_index_arg() @@ -357,7 +365,7 @@ fn main() { .description("creates a proof of ProofOfAttendances for an for the given ceremony index") .options(|app| { app.setting(AppSettings::ColoredHelp) - .setting(AppSettings::AllowLeadingHyphen) + .setting(AppSettings::AllowNegativeNumbers) .account_arg() .ceremony_index_arg() }) diff --git a/node/Cargo.toml b/node/Cargo.toml index cd662c2e..9410a7c4 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -11,7 +11,7 @@ repository = "https://github.com/encointer/encointer-node" # * Align major and minor version with polkadot-sdk major.minor. # * Bump patch version for new releases, and make it the release tag. # * The client should follow this version. -version = "1.8.0" +version = "1.8.1" [[bin]] name = "encointer-node-notee"