Skip to content

Made Pranajaya Dibyacita | Register for OpenGuild FRAME Challenges #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Go to **Participant Registration** section and register to be the workshop parti

```
| 🦄 | Name | Github username | Your current occupation |
| 1 | Made Pranajaya Dibyacita | mdprana | Computer Science Student |
```

- Step 5: `Commit` your code and push to the forked Github repository
Expand Down Expand Up @@ -94,3 +95,8 @@ 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

| 🦄 | Name | Github username | Your current occupation |
| 1 | Made Pranajaya Dibyacita | [mdprana](https://github.com/mdprana) | Computer Science Student |
90 changes: 80 additions & 10 deletions src/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,36 @@ use crate::staking::StakingConfig;
use crate::system::SystemConfig;
use std::collections::HashMap;

pub trait GovernanceConfig: StakingConfig {}
pub trait GovernanceConfig: StakingConfig + SystemConfig {}

pub struct Proposal {
pub struct Proposal<T: GovernanceConfig> {
description: String,
yes_votes: u32,
no_votes: u32,
status: ProposalStatus,
creator: T::AccountId, // Store the creator of the proposal
}

#[derive(Clone)]
#[derive(Clone, PartialEq)]
pub enum ProposalStatus {
Active,
Approved,
Rejected,
}

pub struct GovernancePallet<T: GovernanceConfig> {
pub proposals: HashMap<u32, Proposal>,
pub proposals: HashMap<u32, Proposal<T>>,
pub votes: HashMap<(T::AccountId, u32), bool>, // (voter, proposal_id) -> vote_type
next_proposal_id: u32,
}

impl<T: GovernanceConfig> GovernancePallet<T> {
pub fn new() -> Self {
todo!()
Self {
proposals: HashMap::new(),
votes: HashMap::new(),
next_proposal_id: 0,
}
}

// Create a new proposal
Expand All @@ -35,7 +40,20 @@ impl<T: GovernanceConfig> GovernancePallet<T> {
creator: T::AccountId,
description: String,
) -> Result<u32, &'static str> {
todo!()
let current_id = self.next_proposal_id;

let new_proposal = Proposal {
description,
yes_votes: 0,
no_votes: 0,
status: ProposalStatus::Active,
creator,
};

self.proposals.insert(current_id, new_proposal);
self.next_proposal_id += 1;

Ok(current_id)
}

// Vote on a proposal (true = yes, false = no)
Expand All @@ -45,17 +63,69 @@ impl<T: GovernanceConfig> GovernancePallet<T> {
proposal_id: u32,
vote_type: bool,
) -> Result<(), &'static str> {
todo!()
let vote_key = (voter.clone(), proposal_id);

match self.proposals.get_mut(&proposal_id) {
Some(proposal) => {
if proposal.status != ProposalStatus::Active {
return Err("Cannot vote on inactive proposal");
}

if self.votes.contains_key(&vote_key) {
return Err("Voter has already cast a vote for this proposal");
}

self.votes.insert(vote_key, vote_type);

match vote_type {
true => proposal.yes_votes += 1, // Yes vote
false => proposal.no_votes += 1, // No vote
}

Ok(())
},
None => Err("No proposal found with the given ID"),
}
}

// Get proposal details
pub fn get_proposal(&self, proposal_id: u32) -> Option<&Proposal> {
todo!()
pub fn get_proposal(&self, proposal_id: u32) -> Option<&Proposal<T>> {
self.proposals.get(&proposal_id)
}

// Finalize a proposal (changes status based on votes)
pub fn finalize_proposal(&mut self, proposal_id: u32) -> Result<ProposalStatus, &'static str> {
todo!()
match self.proposals.get_mut(&proposal_id) {
Some(proposal) => {
if proposal.status != ProposalStatus::Active {
return Err("Cannot finalize an already finalized proposal");
}

let new_status = if proposal.yes_votes > proposal.no_votes {
ProposalStatus::Approved
} else {
ProposalStatus::Rejected
};

proposal.status = new_status.clone();

Ok(new_status)
},
None => Err("No proposal found with the given ID"),
}
}

// Get full proposal details including description and creator
pub fn get_proposal_details(
&self,
proposal_id: u32,
) -> Result<(String, T::AccountId), &'static str> {
match self.proposals.get(&proposal_id) {
Some(proposal) => {
Ok((proposal.description.clone(), proposal.creator.clone()))
},
None => Err("No proposal found with the given ID"),
}
}
}

Expand Down
45 changes: 39 additions & 6 deletions src/staking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,65 @@ pub struct StakingPallet<T: StakingConfig> {

impl<T: StakingConfig> StakingPallet<T> {
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!()
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!()
let free_balance = self.get_free_balance(who.clone());

if let Some(new_free_balance) = free_balance.checked_sub(&amount) {
self.free_balances.insert(who.clone(), new_free_balance);

let staked_balance = self.get_staked_balance(who.clone());
if let Some(new_staked_balance) = staked_balance.checked_add(&amount) {
self.staked_balances.insert(who, new_staked_balance);
Ok(())
} else {
self.free_balances.insert(who, free_balance);
Err("Staked balance would overflow")
}
} else {
Err("Not enough free balance to stake")
}
}

// Unstake tokens (move from staked to free)
pub fn unstake(&mut self, who: T::AccountId, amount: T::Balance) -> Result<(), &'static str> {
todo!()
let staked_balance = self.get_staked_balance(who.clone());

if let Some(new_staked_balance) = staked_balance.checked_sub(&amount) {
self.staked_balances.insert(who.clone(), new_staked_balance);

let free_balance = self.get_free_balance(who.clone());
if let Some(new_free_balance) = free_balance.checked_add(&amount) {
self.free_balances.insert(who, new_free_balance);
Ok(())
} else {
self.staked_balances.insert(who, staked_balance);
Err("Free balance would overflow")
}
} else {
Err("Not enough staked balance to unstake")
}
}

// Get free balance for an account
pub fn get_free_balance(&self, who: T::AccountId) -> T::Balance {
todo!()
*self.free_balances.get(&who).unwrap_or(&T::Balance::zero())
}

// Get staked balance for an account
pub fn get_staked_balance(&self, who: T::AccountId) -> T::Balance {
todo!()
*self.staked_balances.get(&who).unwrap_or(&T::Balance::zero())
}
}

Expand Down