Skip to content

Commit

Permalink
change(pallets/communities): split membership and member_rank
Browse files Browse the repository at this point in the history
feat(communities:functions): implement do_promote and do_demote
  • Loading branch information
pandres95 committed Nov 17, 2023
1 parent 514b48c commit 1816d1f
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 11 deletions.
35 changes: 35 additions & 0 deletions pallets/communities/src/functions/membership.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::*;
use crate::traits::member_rank::Mutate;

impl<T: Config> Pallet<T> {
pub(crate) fn ensure_origin_member(
Expand Down Expand Up @@ -37,6 +38,7 @@ impl<T: Config> Pallet<T> {
Ok(None)
}

/// Inserts `who` into the community
pub(crate) fn do_insert_member(community_id: &CommunityIdOf<T>, who: &AccountIdOf<T>) -> DispatchResult {
Members::<T>::try_mutate_exists(community_id, who, |value| {
if value.is_some() {
Expand All @@ -45,6 +47,7 @@ impl<T: Config> Pallet<T> {

// Inserts the member
*value = Some(Default::default());
MemberRanks::<T>::set(community_id, who, Some(Default::default()));

// Increases member count
let members_count = Self::members_count(community_id).unwrap_or_default();
Expand All @@ -54,6 +57,38 @@ impl<T: Config> Pallet<T> {
})
}

pub(crate) fn do_promote_member(community_id: &CommunityIdOf<T>, who: &AccountIdOf<T>) -> DispatchResult {
MemberRanks::<T>::try_mutate(community_id, who, |maybe_rank| {
let Some(rank) = maybe_rank else {
return Err(Error::<T>::NotAMember)?;
};

*maybe_rank = rank.promote();

if maybe_rank.is_none() {
return Err(Error::<T>::ExceededPromoteBound)?;
}

Ok(())
})
}

pub(crate) fn do_demote_member(community_id: &CommunityIdOf<T>, who: &AccountIdOf<T>) -> DispatchResult {
MemberRanks::<T>::try_mutate(community_id, who, |maybe_rank| {
let Some(rank) = maybe_rank else {
return Err(Error::<T>::NotAMember)?;
};

*maybe_rank = rank.demote();

if maybe_rank.is_none() {
return Err(Error::<T>::ExceededDemoteBound)?;
}

Ok(())
})
}

pub(crate) fn do_remove_member(community_id: &T::CommunityId, who: &T::AccountId) -> DispatchResult {
Members::<T>::try_mutate_exists(community_id, who, |value| {
if value.is_none() {
Expand Down
25 changes: 21 additions & 4 deletions pallets/communities/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,14 @@ pub mod pallet {
tokens::Preservation,
Polling,
},
Parameter,
Blake2_128Concat, Parameter,
};
use frame_system::{
ensure_signed,
pallet_prelude::{OriginFor, *},
};
use sp_runtime::traits::StaticLookup;
use traits::rank::MemberRank;
use traits::member_rank;
use types::*;

#[pallet::pallet]
Expand All @@ -213,7 +213,9 @@ pub mod pallet {
type CommunityId: Default + Parameter + MaxEncodedLen + Sync + Send + Ord + Copy;

/// This type represents a rank for a member in a community
type Membership: Default + Parameter + MaxEncodedLen + MemberRank<u8>;
type Membership: Default + Parameter + MaxEncodedLen;

type MemberRank: Default + Parameter + MaxEncodedLen + member_rank::Inspect + member_rank::Mutate;

/// The asset used for governance
type Assets: fungibles::Inspect<Self::AccountId>;
Expand Down Expand Up @@ -251,14 +253,22 @@ pub mod pallet {
#[pallet::getter(fn metadata)]
pub(super) type Metadata<T: Config> = StorageMap<_, Blake2_128Concat, CommunityIdOf<T>, CommunityMetadata>;

/// Stores the information of a community (specified by its
/// Stores the membership information of a community (specified by its
/// [`CommunityId`][`Config::CommunityId`]) member (specified by it's
/// [`AccountId`][`frame_system::Config::AccountId`]).
#[pallet::storage]
#[pallet::getter(fn membership)]
pub(super) type Members<T> =
StorageDoubleMap<_, Blake2_128Concat, CommunityIdOf<T>, Blake2_128Concat, AccountIdOf<T>, MembershipOf<T>>;

/// Stores the rank of a community (specified by its
/// [`CommunityId`][`Config::CommunityId`]) member (specified by it's
/// [`AccountId`][`frame_system::Config::AccountId`]).
#[pallet::storage]
#[pallet::getter(fn member_rank)]
pub(super) type MemberRanks<T> =
StorageDoubleMap<_, Blake2_128Concat, CommunityIdOf<T>, Blake2_128Concat, AccountIdOf<T>, MemberRankOf<T>>;

/// Stores the count of community members. This simplifies the process of
/// keeping track of members' count.
#[pallet::storage]
Expand Down Expand Up @@ -330,6 +340,13 @@ pub mod pallet {
/// The community has exceeded the max amount of enqueded proposals at
/// this moment.
ExceededMaxProposals,
/// A member cannot be promoted since their rank is already at the upper
/// bound. The only option available so far is creating a higher rank.
ExceededPromoteBound,
/// A member cannot be demoted since their rank is already at the upper
/// bound. The options available so far are creating a lower rank, or
/// removing the member.
ExceededDemoteBound,
/// It is not possible to dequeue a proposal
CannotDequeueProposal,
/// A call for the spciefied [Hash][`frame_system::Config::Hash`] is not
Expand Down
8 changes: 2 additions & 6 deletions pallets/communities/src/tests/mock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,12 @@ type Block = frame_system::mocking::MockBlock<Test>;
type WeightInfo = ();

pub type AccountId = u64;
pub type MemberRank = u8;
pub type Balance = u128;
pub type AssetId = u32;
pub type CommunityId = u128;
pub type MembershipPassport = ();

impl pallet_communities::traits::rank::MemberRank<u8> for MembershipPassport {
fn rank(&self) -> u8 {
0
}
}

// Configure a mock runtime to test the pallet.
frame_support::construct_runtime!(
pub enum Test
Expand Down Expand Up @@ -161,6 +156,7 @@ impl pallet_communities::Config for Test {
type Balances = Balances;
type CommunityId = CommunityId;
type Membership = MembershipPassport;
type MemberRank = MemberRank;
type PalletId = CommunitiesPalletId;
type Polls = TestPolls;
}
Expand Down
3 changes: 2 additions & 1 deletion pallets/communities/src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::types::{self, *};
use frame_support::{assert_noop, assert_ok, traits::fungible};
use sp_runtime::traits::BadOrigin;
use sp_runtime::{ArithmeticError, DispatchError};

mod mock;
pub use mock::*;
use mock::*;

type Error = crate::Error<Test>;

Expand Down
1 change: 1 addition & 0 deletions pallets/communities/src/types/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub type AccountIdLookupOf<T> = <<T as SystemConfig>::Lookup as StaticLookup>::S
pub type CommunityIdOf<T> = <T as Config>::CommunityId;
pub type MemberListOf<T> = Vec<AccountIdOf<T>>;
pub type MembershipOf<T> = <T as Config>::Membership;
pub type MemberRankOf<T> = <T as Config>::MemberRank;
pub type VoteOf<T> = Vote<AssetIdOf<T>, AssetBalanceOf<T>>;
pub type PollIndexOf<T> = <<T as Config>::Polls as Polling<Tally<T>>>::Index;
pub type RuntimeOriginOf<T> = <<T as SystemConfig>::RuntimeOrigin as OriginTrait>::PalletsOrigin;

0 comments on commit 1816d1f

Please sign in to comment.