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