Skip to content

Commit

Permalink
Update communities to use latest membership traits
Browse files Browse the repository at this point in the history
  • Loading branch information
olanod committed Jan 16, 2024
1 parent f1eacc6 commit 20fcf04
Show file tree
Hide file tree
Showing 13 changed files with 493 additions and 507 deletions.
686 changes: 344 additions & 342 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pallet-asset-registry = { default-features = false, path = "pallets/asset-regist
pallet-burner = { default-features = false, path = "pallets/burner" }
pallet-payments = { default-features = false, path = "pallets/payments" }

virto-common = { default-features = false, path = "common" }
virto-common = { path = "common" }
runtime-common = { default-features = false, path = "runtime/common" }
kusama-runtime-constants = { default-features = false, path = "runtime/kusama-runtime-constants" }

Expand Down
7 changes: 6 additions & 1 deletion common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#[cfg(feature = "alloc")]
extern crate alloc;
extern crate sp_io;

#[cfg(feature = "runtime")]
use frame_support::pallet_prelude::{Decode, Encode, MaxEncodedLen, TypeInfo};
Expand All @@ -16,3 +15,9 @@ pub use payment_id::PaymentId;
#[cfg_attr(feature = "runtime", derive(Decode, Encode, MaxEncodedLen, TypeInfo))]
#[derive(Debug, Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
pub struct CommunityId(u16);

impl CommunityId {
pub const fn new(id: u16) -> Self {
Self(id)
}
}
27 changes: 18 additions & 9 deletions common/src/membership.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ use crate::CommunityId;
#[cfg(feature = "runtime")]
use frame_support::pallet_prelude::{Decode, Encode, MaxEncodedLen, TypeInfo};

type MembershipIdPart = u32;
type Rank = u8;

/// Unique identifier of a Virto membership NFT
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "runtime", derive(Decode, Encode, MaxEncodedLen, TypeInfo))]
pub struct MembershipId(CommunityId, MembershipIdPart);
pub struct MembershipId(pub CommunityId, pub MembershipIdPart);

type MembershipIdPart = u32;
type Rank = u8;
impl From<MembershipId> for CommunityId {
fn from(id: MembershipId) -> Self {
id.0
}
}

/// Detailed information about a membership
#[cfg_attr(feature = "runtime", derive(Decode, Encode, MaxEncodedLen, TypeInfo))]
Expand All @@ -27,12 +33,15 @@ impl MembershipInfo {
pub fn community(&self) -> &CommunityId {
&self.id.0
}
pub fn rank(&self) -> Rank {
self.rank
}
}

#[cfg(feature = "runtime")]
mod runtime {
use super::*;
use frame_support::traits::membership;
use frame_support::traits::membership::{self, GenericRank};

impl membership::Membership for MembershipInfo {
type Id = MembershipId;
Expand All @@ -46,12 +55,12 @@ mod runtime {
}
}

impl membership::WithRank<Rank> for MembershipInfo {
fn rank(&self) -> &Rank {
&self.rank
impl membership::WithRank<GenericRank> for MembershipInfo {
fn rank(&self) -> GenericRank {
self.rank.into()
}
fn rank_mut(&mut self) -> &mut Rank {
&mut self.rank
fn set_rank(&mut self, rank: impl Into<GenericRank>) {
self.rank = u8::from(rank.into());
}
}
}
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ _task-selector:
rustup component add clippy

check: _check_deps
cargo clippy -p kreivo-runtime -p virto-node -- --deny warnings
cargo clippy --all-targets -- --deny warnings
cargo +nightly fmt --all -- --check

@test crate="" *rest="":
Expand Down
1 change: 1 addition & 0 deletions pallets/communities/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pallet-preimage = { workspace = true }
pallet-referenda = { workspace = true }
pallet-referenda-tracks = { workspace = true }
pallet-scheduler = { workspace = true }
virto-common = { workspace = true }

[features]
default = ["std", "xcm"]
Expand Down
18 changes: 9 additions & 9 deletions pallets/communities/src/functions.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use crate::{
types::{
AccountIdOf, CommunityIdOf, CommunityInfo, CommunityMetadata, CommunityState, ConstSizedField, MembershipId,
AccountIdOf, CommunityIdOf, CommunityInfo, CommunityMetadata, CommunityState, ConstSizedField, MembershipIdOf,
PalletsOriginOf,
},
CommunityIdFor, Config, Error, Info, Metadata, Pallet,
};
use frame_support::{
pallet_prelude::*,
traits::{GenericRank, MembershipInspect, RankedMembership},
traits::membership::{GenericRank, Inspect, WithRank},
};
use sp_runtime::traits::AccountIdConversion;
use sp_std::vec::Vec;
Expand All @@ -22,17 +22,17 @@ impl<T: Config> Pallet<T> {
Self::community(community_id).is_some()
}

pub fn has_membership(who: &AccountIdOf<T>, m: MembershipId<T::CommunityId>) -> bool {
T::Memberships::has_membership(m, who)
pub fn has_membership(who: &AccountIdOf<T>, m: MembershipIdOf<T>) -> bool {
T::MemberMgmt::has_membership(m, who)
}

pub fn member_rank(who: &AccountIdOf<T>, m: MembershipId<T::CommunityId>) -> Option<GenericRank> {
T::Memberships::get_membership(m, who).map(|m| *m.rank())
pub fn member_rank(who: &AccountIdOf<T>, m: MembershipIdOf<T>) -> Option<GenericRank> {
T::MemberMgmt::get_membership(m, who).map(|m| m.rank())
}

pub fn get_memberships(who: &AccountIdOf<T>, community_id: &T::CommunityId) -> Vec<MembershipId<T::CommunityId>> {
T::Memberships::account_memberships(who)
.filter(|m| &m.0 == community_id)
pub fn get_memberships(who: &AccountIdOf<T>, community_id: T::CommunityId) -> Vec<MembershipIdOf<T>> {
T::MemberMgmt::account_memberships(who)
.filter(|id| CommunityIdOf::<T>::from(id.clone()) == community_id)
.collect()
}

Expand Down
79 changes: 47 additions & 32 deletions pallets/communities/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,15 @@ pub mod pallet {
use frame_support::{
pallet_prelude::{ValueQuery, *},
traits::{
fungible::{Inspect, Mutate},
fungibles, EnsureOrigin, GenericRank, MembershipInspect, MembershipMutate, Polling, RankedMembership,
fungible, fungibles,
membership::{self, Inspect, Membership, Mutate, WithRank},
EnsureOrigin, Polling,
},
Blake2_128Concat, Parameter,
};
use frame_system::pallet_prelude::{OriginFor, *};
use sp_runtime::traits::StaticLookup;
use types::*;
use types::{MembershipIdOf, *};

#[pallet::pallet]
pub struct Pallet<T>(_);
Expand All @@ -199,25 +200,28 @@ pub mod pallet {
#[pallet::config]
pub trait Config: frame_system::Config {
/// This type represents an unique ID for the community
type CommunityId: Parameter + MaxEncodedLen + Copy;
type CommunityId: Parameter + MaxEncodedLen + Copy + From<MembershipIdOf<Self>>;

/// This type represents a rank for a member in a community
type Memberships: MembershipInspect<MembershipInfo<Self::CommunityId>, Self::AccountId, MembershipId<Self::CommunityId>>
+ MembershipMutate<MembershipInfo<Self::CommunityId>, Self::AccountId, MembershipId<Self::CommunityId>>;
/// The type holding relevant information of a membership
type Membership: Membership + membership::WithRank;

type Polls: Polling<Tally<Self>, Votes = VoteWeight, Moment = BlockNumberFor<Self>>;
/// Means to manage memberships of a community
type MemberMgmt: membership::Inspect<Self::AccountId, MembershipInfo = Self::Membership, MembershipId = MembershipIdOf<Self>>
+ membership::Mutate<Self::AccountId>;

/// Origin authorized to manage memeberships of an active community
type CommunityMgmtOrigin: EnsureOrigin<Self::RuntimeOrigin>;
type MemberMgmtOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::CommunityId>;

/// Origin authorized to manage memeberships of an active community
type MemberMgmtOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::CommunityId>;
type CommunityMgmtOrigin: EnsureOrigin<Self::RuntimeOrigin>;

type Polls: Polling<Tally<Self>, Votes = VoteWeight, Moment = BlockNumberFor<Self>>;

/// The asset used for governance
type Assets: fungibles::Inspect<Self::AccountId>;

/// Type represents interactions between fungibles (i.e. assets)
type Balances: Inspect<Self::AccountId> + Mutate<Self::AccountId>;
type Balances: fungible::Inspect<Self::AccountId> + fungible::Mutate<Self::AccountId>;

/// Because this pallet emits events, it depends on the runtime's
/// definition of an event.
Expand All @@ -233,7 +237,7 @@ pub mod pallet {

/// The origin of the pallet
#[pallet::origin]
pub type Origin<T> = origin::RawOrigin<CommunityIdOf<T>>;
pub type Origin<T> = origin::RawOrigin<T>;

/// Stores the basic information of the community. If a value exists for a
/// specified [`ComumunityId`][`Config::CommunityId`], this means a
Expand Down Expand Up @@ -276,15 +280,15 @@ pub mod pallet {
},
MemberAdded {
who: AccountIdOf<T>,
membership_id: MembershipId<T::CommunityId>,
membership_id: MembershipIdOf<T>,
},
MemberRemoved {
who: AccountIdOf<T>,
membership_id: MembershipId<T::CommunityId>,
membership_id: MembershipIdOf<T>,
},
MembershipRankUpdated {
membership_id: MembershipId<T::CommunityId>,
rank: GenericRank,
membership_id: MembershipIdOf<T>,
rank: membership::GenericRank,
},
}

Expand Down Expand Up @@ -361,10 +365,14 @@ pub mod pallet {
let who = T::Lookup::lookup(who)?;
let account = Self::community_account(&community_id);
// assume the community has memberships to give out to the new member
let membership_id = T::Memberships::account_memberships(&account)
let membership_id = T::MemberMgmt::account_memberships(&account)
.next()
.ok_or(Error::<T>::CommunityAtCapacity)?;
T::Memberships::update(membership_id, MembershipInfo::new(membership_id), Some(who.clone()))?;
T::MemberMgmt::update(
membership_id.clone(),
T::Membership::new(membership_id.clone()),
Some(who.clone()),
)?;

Self::deposit_event(Event::MemberAdded { who, membership_id });
Ok(())
Expand All @@ -380,16 +388,23 @@ pub mod pallet {
pub fn remove_member(
origin: OriginFor<T>,
who: AccountIdLookupOf<T>,
membership_id: MembershipId<T::CommunityId>,
membership_id: MembershipIdOf<T>,
) -> DispatchResult {
let community_id = T::MemberMgmtOrigin::ensure_origin(origin)?;
let who = T::Lookup::lookup(who)?;
let info = T::Memberships::get_membership(membership_id, &who).ok_or(Error::<T>::NotAMember)?;
ensure!(info.community() == &community_id, Error::<T>::CommunityDoesNotExist);
let info = T::MemberMgmt::get_membership(membership_id.clone(), &who).ok_or(Error::<T>::NotAMember)?;
ensure!(
CommunityIdOf::<T>::from(info.id()) == community_id,
Error::<T>::CommunityDoesNotExist
);

let account = Self::community_account(&community_id);
// Move the membership back to the community resetting any previous stored info
T::Memberships::update(membership_id, MembershipInfo::new(membership_id), Some(account))?;
T::MemberMgmt::update(
membership_id.clone(),
T::Membership::new(membership_id.clone()),
Some(account),
)?;

Self::deposit_event(Event::MemberRemoved { who, membership_id });
Ok(())
Expand All @@ -400,15 +415,15 @@ pub mod pallet {
pub fn promote_member(
origin: OriginFor<T>,
who: AccountIdLookupOf<T>,
membership_id: MembershipId<T::CommunityId>,
membership_id: MembershipIdOf<T>,
) -> DispatchResult {
let _community_id = T::MemberMgmtOrigin::ensure_origin(origin)?;
let who = T::Lookup::lookup(who)?;

let mut m = T::Memberships::get_membership(membership_id, &who).ok_or(Error::<T>::NotAMember)?;
m.rank_mut().promote_by(1.try_into().expect("can promote by 1"));
let rank = *m.rank();
T::Memberships::update(membership_id, m, None)?;
let mut m = T::MemberMgmt::get_membership(membership_id.clone(), &who).ok_or(Error::<T>::NotAMember)?;
let rank = m.rank();
m.set_rank(rank.promote_by(1.try_into().expect("can promote by 1")));
T::MemberMgmt::update(membership_id.clone(), m, None)?;

Self::deposit_event(Event::MembershipRankUpdated { membership_id, rank });
Ok(())
Expand All @@ -419,15 +434,15 @@ pub mod pallet {
pub fn demote_member(
origin: OriginFor<T>,
who: AccountIdLookupOf<T>,
membership_id: MembershipId<T::CommunityId>,
membership_id: MembershipIdOf<T>,
) -> DispatchResult {
let _community_id = T::MemberMgmtOrigin::ensure_origin(origin)?;
let who = T::Lookup::lookup(who)?;

let mut m = T::Memberships::get_membership(membership_id, &who).ok_or(Error::<T>::NotAMember)?;
m.rank_mut().demote_by(1.try_into().expect("can demote by 1"));
let rank = *m.rank();
T::Memberships::update(membership_id, m, None)?;
let mut m = T::MemberMgmt::get_membership(membership_id.clone(), &who).ok_or(Error::<T>::NotAMember)?;
let rank = m.rank();
m.set_rank(rank.demote_by(1.try_into().expect("can promote by 1")));
T::MemberMgmt::update(membership_id.clone(), m, None)?;

Self::deposit_event(Event::MembershipRankUpdated { membership_id, rank });
Ok(())
Expand Down
Loading

0 comments on commit 20fcf04

Please sign in to comment.