From 7b1397a64e38e0e951428118800ad81519e5c986 Mon Sep 17 00:00:00 2001 From: Akhmad Syarifudin Date: Sat, 15 Mar 2025 03:27:54 +0700 Subject: [PATCH] Register for OpenGuild FRAME Challenges --- README.md | 8 ++++++ src/governance.rs | 68 +++++++++++++++++++++++++++++++++++++++++++---- src/staking.rs | 45 ++++++++++++++++++++++++++----- 3 files changed, 110 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index c0ca209..a6ac82c 100644 --- a/README.md +++ b/README.md @@ -94,3 +94,11 @@ OpenGuild is a builder-driven community centered around Polkadot. OpenGuild is b - **Website:** [OpenGuild Website](https://openguild.wtf/) - **Github:** [OpenGuild Labs](https://github.com/openguild-labs) - **Discord**: [Openguild Discord Channel](https://discord.gg/bcjMzxqtD7) + +## Participant Registration + +Add your information to the below list to officially participate in the workshop challenge (This is the first mission of the whole workshop) + +| Emoji | Name | Github Username | Occupations | +| ----- | --------------- | ----------------------------------------------------- | ------------------------ | +| 🦞 | Akhmad Syarifudin | [gethook]([text](https://github.com/gethook)) | Web Developer | diff --git a/src/governance.rs b/src/governance.rs index f71f10b..16d5beb 100644 --- a/src/governance.rs +++ b/src/governance.rs @@ -26,7 +26,12 @@ pub struct GovernancePallet { impl GovernancePallet { pub fn new() -> Self { - todo!() + // todo!() + Self { + proposals: HashMap::new(), + votes: HashMap::new(), + next_proposal_id: 0, + } } // Create a new proposal @@ -35,7 +40,16 @@ impl GovernancePallet { creator: T::AccountId, description: String, ) -> Result { - todo!() + // todo!() + self.next_proposal_id += 1; + let proposal = Proposal { + description, + yes_votes: 0, + no_votes: 0, + status: ProposalStatus::Active, + }; + self.proposals.insert(self.next_proposal_id, proposal); + Ok(self.next_proposal_id) } // Vote on a proposal (true = yes, false = no) @@ -45,17 +59,61 @@ impl GovernancePallet { proposal_id: u32, vote_type: bool, ) -> Result<(), &'static str> { - todo!() + // todo!() + let voted = self.votes.contains_key(&(voter.clone(), proposal_id)); + if voted { + return Err("Already vote"); + } + self.votes.insert((voter, proposal_id), vote_type); + let proposal = self.get_proposal(proposal_id).ok_or("Proposal not found")?; + match proposal.status { + ProposalStatus::Approved => return Err("Proposal finalized"), + ProposalStatus::Rejected => return Err("Proposal finalized"), + ProposalStatus::Active => (), + } + + let mut yes_votes = proposal.yes_votes; + let mut no_votes = proposal.no_votes; + + if vote_type { + yes_votes += 1; + } else { + no_votes += 1; + } + + self.proposals.insert(proposal_id, Proposal { + description: proposal.description.clone(), + yes_votes, + no_votes, + status: ProposalStatus::Active, + }); + + Ok(()) } // Get proposal details pub fn get_proposal(&self, proposal_id: u32) -> Option<&Proposal> { - todo!() + // todo!() + self.proposals.get(&proposal_id) } // Finalize a proposal (changes status based on votes) pub fn finalize_proposal(&mut self, proposal_id: u32) -> Result { - todo!() + // todo!() + let proposal = self.get_proposal(proposal_id).ok_or("Proposal not found")?; + let mut status = ProposalStatus::Rejected; + if proposal.yes_votes > proposal.no_votes { + status = ProposalStatus::Approved; + } + + self.proposals.insert(proposal_id, Proposal { + description: proposal.description.clone(), + yes_votes: proposal.yes_votes, + no_votes: proposal.no_votes, + status: status.clone(), + }); + + Ok(status) } } diff --git a/src/staking.rs b/src/staking.rs index 7bd646e..f94994e 100644 --- a/src/staking.rs +++ b/src/staking.rs @@ -16,32 +16,65 @@ pub struct StakingPallet { impl StakingPallet { pub fn new() -> Self { - todo!() + Self { + free_balances: HashMap::new(), + staked_balances: HashMap::new(), + } } // Set free balance for an account pub fn set_balance(&mut self, who: T::AccountId, amount: T::Balance) { - todo!() + // todo!() + self.free_balances.insert(who, amount); } // Stake tokens (move from free to staked) pub fn stake(&mut self, who: T::AccountId, amount: T::Balance) -> Result<(), &'static str> { - todo!() + // todo!() + let curr_free_balances = self.get_free_balance(who.clone()); + let curr_staked_balances = self.get_staked_balance(who.clone()); + + let new_free_balances = curr_free_balances + .checked_sub(&amount) + .ok_or("No enough funds")?; + let new_staked_balances = curr_staked_balances + .checked_add(&amount) + .ok_or("Overflow")?; + self.free_balances.insert(who.clone(), new_free_balances); + self.staked_balances.insert(who.clone(), new_staked_balances); + + Ok(()) } // Unstake tokens (move from staked to free) pub fn unstake(&mut self, who: T::AccountId, amount: T::Balance) -> Result<(), &'static str> { - todo!() + // todo!() + let curr_free_balances = self.get_free_balance(who.clone()); + let curr_staked_balances = self.get_staked_balance(who.clone()); + + let new_free_balances = curr_free_balances + .checked_add(&amount) + .ok_or("Overflow")?; + let new_staked_balances = curr_staked_balances + .checked_sub(&amount) + .ok_or("No enough funds")?; + self.free_balances.insert(who.clone(), new_free_balances); + self.staked_balances.insert(who.clone(), new_staked_balances); + + Ok(()) + } // Get free balance for an account pub fn get_free_balance(&self, who: T::AccountId) -> T::Balance { - todo!() + // todo!() + self.free_balances.get(&who).copied().unwrap_or(T::Balance::zero()) } // Get staked balance for an account pub fn get_staked_balance(&self, who: T::AccountId) -> T::Balance { - todo!() + // todo!() + self.staked_balances.get(&who).copied().unwrap_or(T::Balance::zero()) } }