voting/
lib.rs

1use anchor_lang::prelude::*;
2declare_id!("87WLQAHeR49beh5N1M7SCMyv9fvp2hkMSiwG88zqUXd9");
3
4
5
6#[program]
7pub mod voting {
8    use super::*;
9   
10
11  
12    
13    pub fn create(ctx: Context<Create>, topic_: String, applications_deadline:i32, voting_deadline:i32) -> Result<()> {
14        let topic = &mut ctx.accounts.vote_account;
15        topic.topic=topic_;
16        topic.options_count=0;
17        topic.applications_deadline=Clock::get()?.unix_timestamp + (applications_deadline * 86400) as i64;
18        topic.voting_deadline=Clock::get()?.unix_timestamp + (applications_deadline * 86400) as i64 + (voting_deadline * 86400) as i64;
19        topic.use_organisation=false;
20
21        Ok(())
22    }
23    pub fn create_with_organisation(ctx: Context<Create>, topic_: String, applications_deadline:i32, voting_deadline:i32, organisation:Pubkey) -> Result<()> {
24        let topic = &mut ctx.accounts.vote_account;
25        topic.topic=topic_;
26        topic.options_count=0;
27        topic.applications_deadline=Clock::get()?.unix_timestamp + (applications_deadline * 86400) as i64;
28        topic.voting_deadline=Clock::get()?.unix_timestamp + (applications_deadline * 86400) as i64 + (voting_deadline * 86400) as i64;
29        topic.use_organisation=true;
30        topic.organisation=organisation;
31        Ok(())
32    }
33    pub fn add_option(ctx: Context<AddOption>, option_name: String) -> Result<()> {
34        let topic = &mut ctx.accounts.vote_account;
35        if topic.applications_deadline < Clock::get()?.unix_timestamp{
36            Err(VotingErr::ApplicationIsOver)?;
37        }
38        topic.options_count+=1;
39        let option =&mut ctx.accounts.option_account;
40        option.name=option_name;
41        option.votes=0;
42        option.id=topic.options_count;
43        option.bump=*ctx.bumps.get("option_account").unwrap(); 
44        Ok(())
45    }
46
47    pub fn create_organisation(ctx: Context<CreateOrganisation>,name:String)-> Result<()>{
48        let organisation = &mut ctx.accounts.organisation_account;
49        organisation.name=name;
50        organisation.participants=0;
51        organisation.authority= ctx.accounts.user.key();
52        Ok(())
53    }
54
55    pub fn join_organisation(ctx: Context<JoinOrganisation>)-> Result<()>{
56        let participant = &mut ctx.accounts.organisation_participant;
57        participant.allowed_to_vote=false;
58        let organisation = &mut ctx.accounts.organisation_account;
59        organisation.participants+=1;
60        Ok(())
61    }
62
63    pub fn allow_voting(ctx: Context<VotingRight>)-> Result<()>{
64        let participant = &mut ctx.accounts.participant;
65        participant.allowed_to_vote=true;
66        Ok(())
67    } 
68
69    pub fn disallow_voting(ctx: Context<VotingRight>)-> Result<()>{
70        let participant = &mut ctx.accounts.participant;
71        participant.allowed_to_vote=false;
72        Ok(())
73    } 
74
75    pub fn vote(ctx: Context<Vote>)-> Result<()>{
76        let topic = &mut ctx.accounts.vote_account;
77        if topic.applications_deadline > Clock::get()?.unix_timestamp{
78            Err(VotingErr::VotingNotStarted)?;
79        }
80        if topic.voting_deadline < Clock::get()?.unix_timestamp{
81            Err(VotingErr::VotingIsOver)?;
82        } 
83        if topic.use_organisation==false{
84        let option =&mut ctx.accounts.option_account;
85        option.votes+=1;
86        let voter =&mut ctx.accounts.voter_account;
87        voter.voted=true;}
88        else{
89            Err(VotingErr::OrganisationNeeded)?;
90        }
91        Ok(())
92    }
93    pub fn vote_with_organisation(ctx: Context<VoteWithOrganisation>)-> Result<()>{
94        let topic = &mut ctx.accounts.vote_account;
95        if topic.applications_deadline > Clock::get()?.unix_timestamp{
96            Err(VotingErr::VotingNotStarted)?;
97        }
98        if topic.voting_deadline < Clock::get()?.unix_timestamp{
99            Err(VotingErr::VotingIsOver)?;
100        } 
101        if topic.use_organisation==true{
102            let participant = &mut ctx.accounts.organisation_participant;
103            if participant.allowed_to_vote==true{
104                let option =&mut ctx.accounts.option_account;
105                option.votes+=1;
106                let voter =&mut ctx.accounts.voter_account;
107                voter.voted=true;
108            }else{
109                Err(VotingErr::NoPermisson)?;
110            }
111        }else{
112            Err(VotingErr::NoOrganisation)?;
113        }
114        Ok(())
115    }
116}
117
118#[derive(Accounts)]
119pub struct Create<'info> {
120    #[account(init, payer = user, space = 32 + 32 + 16)]
121    pub vote_account: Account<'info, VoteTopic>,
122    #[account(mut)]
123    pub user: Signer<'info>,
124    pub system_program: Program <'info, System>,
125    
126}
127
128
129#[derive(Accounts)]
130pub struct AddOption<'info> {
131    #[account(mut)]
132    pub vote_account: Account<'info, VoteTopic>,
133    #[account(init, payer = user, space = 32 + 32,seeds=[vote_account.key().as_ref(),&[vote_account.options_count +1]],bump)]
134    pub option_account: Account<'info, VoteOption>,
135    #[account(mut)]
136    pub user: Signer<'info>,
137    pub system_program: Program <'info, System>,
138}
139
140#[derive(Accounts)]
141pub struct CreateOrganisation<'info>{
142    #[account(init, payer = user, space = 32 + 32 + 32)]
143    pub organisation_account: Account<'info, Organisation>,
144    #[account(mut)]
145    pub user: Signer<'info>,
146    pub system_program: Program <'info, System>,
147}
148
149#[derive(Accounts)]
150pub struct JoinOrganisation<'info>{
151    #[account(mut)]
152    pub organisation_account: Account<'info, Organisation>,
153    #[account(init, payer = user, space = 32 + 32 ,seeds=[organisation_account.key().as_ref(),user.key().as_ref()],bump)]
154    pub organisation_participant: Account<'info, OrganisationParticipant>,
155    #[account(mut)]
156    pub user: Signer<'info>,
157    pub system_program: Program <'info, System>,
158}
159
160#[derive(Accounts)]
161pub struct VotingRight<'info>{
162    #[account(mut, has_one = authority)]
163    pub organisation_account: Account<'info, Organisation>,
164    #[account(mut)]
165    pub authority: Signer<'info>,
166    #[account(mut)]
167    pub participant: Account<'info, OrganisationParticipant>,
168}
169
170
171#[derive(Accounts)]
172pub struct Vote<'info> {
173    #[account(mut)]
174    pub vote_account: Account<'info, VoteTopic>,
175    #[account(mut ,seeds=[vote_account.key().as_ref(),&[(option_account.id)]],bump=option_account.bump)]
176    pub option_account: Account<'info, VoteOption>,
177    #[account(init, payer=user,space=16 ,seeds=[vote_account.key().as_ref(),user.key().as_ref()],bump)]
178    pub voter_account: Account<'info, Voter>,
179    #[account(mut)]
180    pub user: Signer<'info>,
181    pub system_program: Program <'info, System>,
182}
183
184#[derive(Accounts)]
185pub struct VoteWithOrganisation<'info> {
186    #[account(mut)]
187    pub vote_account: Account<'info, VoteTopic>,
188    #[account(mut ,seeds=[vote_account.key().as_ref(),&[(option_account.id)]],bump=option_account.bump)]
189    pub option_account: Account<'info, VoteOption>,
190    #[account(init, payer=user,space=16 ,seeds=[vote_account.key().as_ref(),user.key().as_ref()],bump)]
191    pub voter_account: Account<'info, Voter>,
192    #[account(mut, seeds=[vote_account.organisation.as_ref(),user.key().as_ref()],bump)]
193    pub organisation_participant: Account<'info, OrganisationParticipant>,
194    #[account(mut)]
195    pub user: Signer<'info>,
196    pub system_program: Program <'info, System>,
197}
198
199#[account]
200pub struct VoteTopic {
201pub topic: String,
202pub options_count:u8,
203pub applications_deadline:i64,
204pub voting_deadline:i64,
205pub use_organisation: bool,
206pub organisation: Pubkey,
207}
208
209#[account]
210pub struct Organisation{
211    pub name: String,
212    pub participants: u128,
213    pub authority: Pubkey,
214}
215
216#[account]
217pub struct OrganisationParticipant{
218    pub allowed_to_vote:bool
219}
220
221#[account]
222pub struct VoteOption {
223pub id:u8,
224pub name: String,
225pub votes: u64,
226pub bump: u8
227}
228
229#[account]
230pub struct Voter {
231pub voted:bool
232}
233
234
235#[error_code]
236pub enum VotingErr {
237    #[msg("Application period is over!")]
238    ApplicationIsOver,
239
240    #[msg("Voting period has not started yet!")]
241    VotingNotStarted,
242
243    #[msg("Voting period is over!")]
244    VotingIsOver,
245
246    #[msg("Please use 'vote' function instead of 'vote_with_organisation'!")]
247    NoOrganisation,
248
249    #[msg("You are not allowed to vote!")]
250    NoPermisson,
251
252    #[msg("Please use 'vote_with_organisation' function instead of 'vote'!")]
253    OrganisationNeeded,
254}
255