Skip to content

Commit

Permalink
enable democracy (#366)
Browse files Browse the repository at this point in the history
* fixes for new democracy tutorial

* enable enactment and add command

* verbose list-communities

* fixed CI + nice date info for list-proposals

* cosmetics

* parse nominal income as float

* fixes

* move more fetch helpers to APi traits

* move bazaar fetchers as well

* carg fix

* fmt

* add get_cycle_duration

* add electorate estimate
  • Loading branch information
brenzi authored Mar 24, 2024
1 parent 7db756e commit ba9c25d
Show file tree
Hide file tree
Showing 24 changed files with 605 additions and 244 deletions.
13 changes: 7 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ name = "encointer-client-notee"
authors = ["encointer.org <[email protected]>"]
edition = "2021"
#keep with node version. major, minor and patch
version = "1.8.1"
version = "1.8.2"

[dependencies]
# todo migrate to clap >=3 https://github.com/encointer/encointer-node/issues/107
chrono = "0.4.35"
clap = "2.33"
clap-nested = "0.4.0"
env_logger = { workspace = true }
Expand Down
8 changes: 5 additions & 3 deletions client/bootstrap_demo_community.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
import json
import os
import click
from time import sleep

from py_client.client import Client
from py_client.scheduler import CeremonyPhase
from py_client.ipfs import Ipfs, ASSETS_PATH


account1 = '//Alice'
account2 = '//Bob'
account3 = '//Charlie'
Expand Down Expand Up @@ -359,8 +361,8 @@ def test_democracy(client, cid):
client.vote("//Bob", 1, "aye", [[cid, cindex]])
client.vote("//Charlie", 1, "aye", [[cid, cindex]])


client.await_block(21)
print("waiting 5min for confirmation phase to end")
sleep(60*5+1)
client.update_proposal_state("//Alice", 1)
proposals = client.list_proposals()
print(proposals)
Expand All @@ -370,7 +372,7 @@ def test_democracy(client, cid):

@click.command()
@click.option('--client', default='../target/release/encointer-client-notee', help='Client binary to communicate with the chain.')
@click.option('--signer', help='optional account keypair creating the community')
@click.option('--signer', default='//Bob', help='optional account keypair creating the community')
@click.option('-u', '--url', default='ws://127.0.0.1', help='URL of the chain.')
@click.option('-p', '--port', default='9944', help='ws-port of the chain.')
@click.option('-l', '--ipfs-local', is_flag=True, help='if set, local ipfs node is used.')
Expand Down
48 changes: 48 additions & 0 deletions client/encointer-api-client-extension/src/bazaar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use crate::Api;
use encointer_node_notee_runtime::AccountId;
use encointer_primitives::{
bazaar::{Business, BusinessIdentifier, OfferingData},
communities::CommunityIdentifier,
};

use substrate_api_client::{ac_compose_macros::rpc_params, rpc::Request};

#[maybe_async::maybe_async(?Send)]
pub trait BazaarApi {
async fn get_businesses(&self, cid: CommunityIdentifier) -> Option<Vec<Business<AccountId>>>;
async fn get_offerings(&self, cid: CommunityIdentifier) -> Option<Vec<OfferingData>>;
async fn get_offerings_for_business(
&self,
cid: CommunityIdentifier,
account_id: AccountId,
) -> Option<Vec<OfferingData>>;
}

#[maybe_async::maybe_async(?Send)]
impl BazaarApi for Api {
async fn get_businesses(&self, cid: CommunityIdentifier) -> Option<Vec<Business<AccountId>>> {
self.client()
.request("encointer_bazaarGetBusinesses", rpc_params![cid])
.await
.expect("Could not find any businesses...")
}

async fn get_offerings(&self, cid: CommunityIdentifier) -> Option<Vec<OfferingData>> {
self.client()
.request("encointer_bazaarGetOfferings", rpc_params![cid])
.await
.expect("Could not find any business offerings...")
}

async fn get_offerings_for_business(
&self,
cid: CommunityIdentifier,
account_id: AccountId,
) -> Option<Vec<OfferingData>> {
let b_id = BusinessIdentifier::new(cid, account_id);
self.client()
.request("encointer_bazaarGetOfferingsForBusiness", rpc_params![b_id])
.await
.expect("Could not find any business offerings...")
}
}
84 changes: 81 additions & 3 deletions client/encointer-api-client-extension/src/ceremonies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ 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_node_notee_runtime::{CeremonyIndexType, Hash};
use encointer_primitives::{
ceremonies::{
Assignment, AssignmentCount, CommunityCeremony, MeetupIndexType, MeetupTimeOffsetType,
ParticipantIndexType,
ParticipantIndexType, ReputationCountType, ReputationLifetimeType,
},
communities::Location,
};
Expand All @@ -15,7 +15,6 @@ 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";
Expand Down Expand Up @@ -129,6 +128,31 @@ pub trait CeremoniesApi {
account_id: AccountId,
maybe_at: Option<Hash>,
) -> Result<u32>;
async fn get_global_reputation_count(
&self,
cindex: CeremonyIndexType,
maybe_at: Option<Hash>,
) -> Result<ReputationCountType>;
async fn get_reputation_count(
&self,
community_ceremony: CommunityCeremony,
maybe_at: Option<Hash>,
) -> Result<ReputationCountType>;
async fn get_reputation_lifetime(
&self,
maybe_at: Option<Hash>,
) -> Result<ReputationLifetimeType>;
async fn get_participant_attestation_index(
&self,
key: CommunityCeremony,
accountid: &encointer_node_notee_runtime::AccountId,
maybe_at: Option<Hash>,
) -> Option<ParticipantIndexType>;
async fn get_attestee_count(
&self,
key: CommunityCeremony,
maybe_at: Option<Hash>,
) -> ParticipantIndexType;
}

#[maybe_async::maybe_async(?Send)]
Expand Down Expand Up @@ -476,6 +500,60 @@ impl CeremoniesApi for Api {
.await?
.ok_or_else(|| ApiClientError::Other("MeetupParticipantCountVote don't exist".into()))
}

async fn get_reputation_count(
&self,
community_ceremony: CommunityCeremony,
maybe_at: Option<Hash>,
) -> Result<ReputationCountType> {
self.get_storage_map("EncointerCeremonies", "ReputationCount", community_ceremony, maybe_at)
.await?
.ok_or_else(|| ApiClientError::Other("ReputationCount not found".into()))
}
async fn get_global_reputation_count(
&self,
cindex: CeremonyIndexType,
maybe_at: Option<Hash>,
) -> Result<ReputationCountType> {
self.get_storage_map("EncointerCeremonies", "GlobalReputationCount", cindex, maybe_at)
.await?
.ok_or_else(|| ApiClientError::Other("GlobalReputationCount not found".into()))
}
async fn get_reputation_lifetime(
&self,
maybe_at: Option<Hash>,
) -> Result<ReputationLifetimeType> {
self.get_storage("EncointerCeremonies", "ReputationLifetime", maybe_at)
.await?
.ok_or_else(|| ApiClientError::Other("ReputationLifetime not found".into()))
}
async fn get_attestee_count(
&self,
key: CommunityCeremony,
maybe_at: Option<Hash>,
) -> ParticipantIndexType {
self.get_storage_map("EncointerCeremonies", "AttestationCount", key, maybe_at)
.await
.unwrap()
.unwrap_or(0)
}

async fn get_participant_attestation_index(
&self,
key: CommunityCeremony,
accountid: &encointer_node_notee_runtime::AccountId,
maybe_at: Option<Hash>,
) -> Option<ParticipantIndexType> {
self.get_storage_double_map(
"EncointerCeremonies",
"AttestationIndex",
key,
accountid,
maybe_at,
)
.await
.unwrap()
}
}

async fn get_bootstrapper_or_reputable(
Expand Down
83 changes: 81 additions & 2 deletions client/encointer-api-client-extension/src/communities.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@
use crate::{Api, Result};
use encointer_primitives::communities::{CommunityIdentifier, Location};
use substrate_api_client::{ac_compose_macros::rpc_params, rpc::Request};
use encointer_node_notee_runtime::Hash;
use encointer_primitives::{
balances::{BalanceType, Demurrage},
communities::{CidName, CommunityIdentifier, CommunityMetadata, Location},
};
use std::str::FromStr;
use substrate_api_client::{ac_compose_macros::rpc_params, rpc::Request, GetStorage};

#[maybe_async::maybe_async(?Send)]
pub trait CommunitiesApi {
async fn get_locations(&self, cid: CommunityIdentifier) -> Result<Vec<Location>>;
async fn get_community_identifiers(
&self,
maybe_at: Option<Hash>,
) -> Option<Vec<CommunityIdentifier>>;
async fn get_nominal_income(
&self,
cid: CommunityIdentifier,
maybe_at: Option<Hash>,
) -> Option<BalanceType>;
async fn get_demurrage_per_block(
&self,
cid: CommunityIdentifier,
maybe_at: Option<Hash>,
) -> Option<Demurrage>;
async fn get_community_metadata(
&self,
cid: CommunityIdentifier,
maybe_at: Option<Hash>,
) -> Option<CommunityMetadata>;
async fn get_cid_names(&self) -> Option<Vec<CidName>>;
async fn verify_cid(&self, cid: &str, maybe_at: Option<Hash>) -> CommunityIdentifier;
}

#[maybe_async::maybe_async(?Send)]
Expand All @@ -16,4 +42,57 @@ impl CommunitiesApi for Api {
.await?;
Ok(locations)
}
async fn get_community_identifiers(
&self,
maybe_at: Option<Hash>,
) -> Option<Vec<CommunityIdentifier>> {
self.get_storage("EncointerCommunities", "CommunityIdentifiers", maybe_at)
.await
.unwrap()
}

async fn get_nominal_income(
&self,
cid: CommunityIdentifier,
maybe_at: Option<Hash>,
) -> Option<BalanceType> {
self.get_storage_map("EncointerCommunities", "NominalIncome", cid, maybe_at)
.await
.unwrap()
}

async fn get_demurrage_per_block(
&self,
cid: CommunityIdentifier,
maybe_at: Option<Hash>,
) -> Option<Demurrage> {
self.get_storage_map("EncointerBalances", "DemurragePerBlock", cid, maybe_at)
.await
.unwrap()
}
async fn get_community_metadata(
&self,
cid: CommunityIdentifier,
maybe_at: Option<Hash>,
) -> Option<CommunityMetadata> {
self.get_storage_map("EncointerCommunities", "CommunityMetadata", cid, maybe_at)
.await
.unwrap()
}

/// This rpc needs to have offchain indexing enabled in the node.
async fn get_cid_names(&self) -> Option<Vec<CidName>> {
self.client().request("encointer_getAllCommunities", rpc_params![]).await.expect(
"No communities returned. Are you running the node with `--enable-offchain-indexing true`?",
)
}

async fn verify_cid(&self, cid: &str, maybe_at: Option<Hash>) -> CommunityIdentifier {
let cids = self.get_community_identifiers(maybe_at).await.expect("no community registered");
let cid = CommunityIdentifier::from_str(cid).unwrap();
if !cids.contains(&cid) {
panic!("cid {cid} does not exist on chain");
}
cid
}
}
23 changes: 23 additions & 0 deletions client/encointer-api-client-extension/src/democracy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use crate::{Api, Moment, Result};
use std::time::Duration;
use substrate_api_client::GetStorage;

#[maybe_async::maybe_async(?Send)]
pub trait DemocracyApi {
async fn get_proposal_lifetime(&self) -> Result<Duration>;
async fn get_confirmation_period(&self) -> Result<Duration>;
}

#[maybe_async::maybe_async(?Send)]
impl DemocracyApi for Api {
async fn get_proposal_lifetime(&self) -> Result<Duration> {
Ok(Duration::from_millis(
self.get_constant::<Moment>("EncointerDemocracy", "ProposalLifetime").await?,
))
}
async fn get_confirmation_period(&self) -> Result<Duration> {
Ok(Duration::from_millis(
self.get_constant::<Moment>("EncointerDemocracy", "ConfirmationPeriod").await?,
))
}
}
Loading

0 comments on commit ba9c25d

Please sign in to comment.