1pub mod assertions;
2pub mod constants;
3pub mod errors;
4mod gateway;
5pub mod instructions;
6pub mod state;
7
8use {
9 anchor_lang::prelude::*,
10 hpl_toolkit::utils::ShortVec,
11 instructions::*,
12 state::{
13 AssociatedProgram, BadgeCriteria, Global, Profile, ProfileDataConfig, Project,
14 SerializableActions, Service, User,
15 },
16};
17
18pub use spl_account_compression::Node;
20
21declare_id!("HivezrprVqHR6APKKQkkLHmUG8waZorXexEBRZWh5LRm");
22
23#[program]
24pub mod hpl_hive_control {
25
26 use std::str::FromStr;
27
28 use errors::HplHiveControlError;
29 use hpl_toolkit::{
30 prelude::ControlledMerkleTrees,
31 schema::{SchemaContainer, ToSchema},
32 };
33
34 use super::*;
35
36 pub fn init_global(ctx: Context<InitGlobal>, args: InitGlobalArgs) -> Result<()> {
39 instructions::init_global(ctx, args)
40 }
41
42 pub fn set_global_config(
45 ctx: Context<SetGlobalConfig>,
46 args: SetGlobalConfigArgs,
47 ) -> Result<()> {
48 assertions::assert_program_authority(
49 ctx.accounts.program.to_account_info(),
50 ctx.accounts.program_data.to_account_info(),
51 ctx.accounts.authority.key,
52 )?;
53 instructions::set_global_config(ctx, args)
54 }
55
56 pub fn withdraw_proceedings(ctx: Context<WithdrawProceedings>, amount: u64) -> Result<()> {
59 assertions::assert_program_authority(
60 ctx.accounts.program.to_account_info(),
61 ctx.accounts.program_data.to_account_info(),
62 ctx.accounts.authority.key,
63 )?;
64 instructions::withdraw_proceedings(ctx, amount)
65 }
66
67 pub fn create_new_user_tree(ctx: Context<CreateNewUserTree>) -> Result<()> {
68 instructions::create_new_user_tree(ctx)
69 }
70
71 pub fn platform_gate(ctx: Context<PlatformGate>, args: PlatformGateArgs) -> Result<()> {
72 instructions::platform_gate(ctx, args)
73 }
74
75 pub fn create_project(ctx: Context<CreateProject>, args: CreateProjectArgs) -> Result<()> {
77 instructions::platform_gate_fn(
78 SerializableActions::CreateProject,
79 None,
80 &ctx.accounts.project,
81 ctx.accounts.authority.key(),
82 &ctx.accounts.payer,
83 &ctx.accounts.vault,
84 &None,
85 &ctx.accounts.system_program,
86 &ctx.accounts.instructions_sysvar,
87 ID,
88 true,
89 )?;
90
91 instructions::create_project(ctx, args)
92 }
93
94 pub fn change_driver(mut ctx: Context<ChangeDriver>) -> Result<()> {
96 instructions::change_driver(&mut ctx)?;
97
98 instructions::platform_gate_fn(
99 SerializableActions::ManageProjectDriver,
100 None,
101 &ctx.accounts.project,
102 ctx.accounts.authority.key(),
103 &ctx.accounts.payer,
104 &ctx.accounts.vault,
105 &ctx.accounts.delegate_authority,
106 &ctx.accounts.system_program,
107 &ctx.accounts.instructions_sysvar,
108 ID,
109 true,
110 )
111 }
112
113 pub fn change_authority(mut ctx: Context<ChangeAuthority>) -> Result<()> {
115 instructions::change_authority(&mut ctx)?;
116 instructions::platform_gate_fn(
117 SerializableActions::ManageProjectDriver,
118 None,
119 &ctx.accounts.project,
120 ctx.accounts.authority.key(),
121 &ctx.accounts.payer,
122 &ctx.accounts.vault,
123 &ctx.accounts.delegate_authority,
124 &ctx.accounts.system_program,
125 &ctx.accounts.instructions_sysvar,
126 ID,
127 true,
128 )
129 }
130
131 pub fn add_remove_criteria(
133 mut ctx: Context<AddRemoveCriteria>,
134 args: AddRemoveCriteriaArgs,
135 ) -> Result<()> {
136 instructions::add_remove_criteria(&mut ctx, args)?;
137 instructions::platform_gate_fn(
138 SerializableActions::ManageCriterias,
139 None,
140 &ctx.accounts.project,
141 ctx.accounts.authority.key(),
142 &ctx.accounts.payer,
143 &ctx.accounts.vault,
144 &ctx.accounts.delegate_authority,
145 &ctx.accounts.system_program,
146 &ctx.accounts.instructions_sysvar,
147 ID,
148 true,
149 )
150 }
151
152 pub fn create_new_profiles_tree(
154 mut ctx: Context<CreateNewProfilesTree>,
155 args: CreateNewProfilesTreeArgs,
156 ) -> Result<()> {
157 instructions::create_new_profiles_tree(&mut ctx, args)?;
158 instructions::platform_gate_fn(
159 SerializableActions::PublicLow,
160 None,
161 &ctx.accounts.project,
162 ctx.accounts.authority.key(),
163 &ctx.accounts.payer,
164 &ctx.accounts.vault,
165 &ctx.accounts.delegate_authority,
166 &ctx.accounts.system_program,
167 &ctx.accounts.instructions_sysvar,
168 ID,
169 true,
170 )
171 }
172
173 pub fn create_delegate_authority(
175 mut ctx: Context<CreateDelegateAuthority>,
176 args: CreateDelegateAuthorityArgs,
177 ) -> Result<()> {
178 instructions::create_delegate_authority(&mut ctx, args)?;
179 instructions::platform_gate_fn(
180 SerializableActions::ManageDelegateAuthority,
181 None,
182 &ctx.accounts.project,
183 ctx.accounts.authority.key(),
184 &ctx.accounts.payer,
185 &ctx.accounts.vault,
186 &None,
187 &ctx.accounts.system_program,
188 &ctx.accounts.instructions_sysvar,
189 ID,
190 true,
191 )
192 }
193
194 pub fn add_remove_delegation(
196 mut ctx: Context<ModifyDelegate>,
197 args: AddRemoveDelegationArgs,
198 ) -> Result<()> {
199 instructions::add_remove_delegation(&mut ctx, args)?;
200 instructions::platform_gate_fn(
201 SerializableActions::ManageDelegateAuthority,
202 None,
203 &ctx.accounts.project,
204 ctx.accounts.authority.key(),
205 &ctx.accounts.payer,
206 &ctx.accounts.vault,
207 &None,
208 &ctx.accounts.system_program,
209 &ctx.accounts.instructions_sysvar,
210 ID,
211 true,
212 )
213 }
214
215 pub fn initialize_badge_criteria<'info>(
216 mut ctx: Context<'_, '_, '_, 'info, InitializeBadgeCriteria<'info>>,
217 args: InitializeBadgeCriteriaArgs,
218 ) -> Result<()> {
219 instructions::initialize_badge_criteria(&mut ctx, args)
220 }
221
222 pub fn claim_badge_criteria<'info>(
223 mut ctx: Context<'_, '_, '_, 'info, ClaimBadgeCriteria<'info>>,
224 args: ClaimBadgeCriteriaArgs,
225 ) -> Result<()> {
226 instructions::claim_badge_criteria(&mut ctx, args)
227 }
228
229 pub fn update_badge_criteria<'info>(
230 mut ctx: Context<'_, '_, '_, 'info, UpdateBadgeCriteria<'info>>,
231 args: UpdateBadgeCriteriaArgs,
232 ) -> Result<()> {
233 instructions::update_badge_criteria(&mut ctx, args)
234 }
235
236 pub fn new_user(ctx: Context<NewUser>, args: NewUserArgs) -> Result<u64> {
238 assertions::assert_global_driver(&ctx.accounts.global, &ctx.accounts.authority)?;
239 instructions::new_user(ctx, args)
240 }
241
242 pub fn update_user<'info>(
244 ctx: Context<'_, '_, '_, 'info, UpdateUser<'info>>,
245 args: UpdateUserArgs,
246 ) -> Result<()> {
247 assertions::assert_global_driver(&ctx.accounts.global, &ctx.accounts.authority)?;
248 instructions::update_user(ctx, args)
249 }
250
251 pub fn new_profile(mut ctx: Context<NewProfile>, args: NewProfileArgs) -> Result<()> {
253 assertions::assert_global_driver(&ctx.accounts.global, &ctx.accounts.authority)?;
254 instructions::new_profile(&mut ctx, args)?;
255
256 instructions::platform_gate_fn(
257 SerializableActions::PublicLow,
258 None,
259 &ctx.accounts.project,
260 ctx.accounts.authority.key(),
261 &ctx.accounts.payer,
262 &ctx.accounts.vault,
263 &None,
264 &ctx.accounts.system_program,
265 &ctx.accounts.instructions_sysvar,
266 ID,
267 false,
268 )?;
269
270 if ctx.accounts.project.subsidize_fees {
271 instructions::refund(
272 0,
273 &ctx.accounts.project,
274 &ctx.accounts.payer,
275 &ctx.accounts.instructions_sysvar,
276 )?;
277 }
278
279 Ok(())
280 }
281
282 pub fn update_profile<'info>(
284 mut ctx: Context<'_, '_, '_, 'info, UpdateProfile<'info>>,
285 args: UpdateProfileArgs,
286 ) -> Result<()> {
287 assertions::assert_global_driver(&ctx.accounts.global, &ctx.accounts.authority)?;
288 instructions::update_profile(&mut ctx, args)?;
289
290 instructions::platform_gate_fn(
291 SerializableActions::PublicHigh,
292 None,
293 &ctx.accounts.project,
294 ctx.accounts.authority.key(),
295 &ctx.accounts.payer,
296 &ctx.accounts.vault,
297 &None,
298 &ctx.accounts.system_program,
299 &ctx.accounts.instructions_sysvar,
300 ID,
301 false,
302 )?;
303
304 if ctx.accounts.project.subsidize_fees {
305 instructions::refund(
306 0,
307 &ctx.accounts.project,
308 &ctx.accounts.payer,
309 &ctx.accounts.instructions_sysvar,
310 )?;
311 }
312
313 Ok(())
314 }
315
316 pub fn update_platform_data<'info>(
318 mut ctx: Context<'_, '_, '_, 'info, UpdatePlatformData<'info>>,
319 args: UpdatePlatformDataArgs,
320 ) -> Result<()> {
321 instructions::update_platform_data(&mut ctx, args)?;
322
323 instructions::platform_gate_fn(
324 SerializableActions::PublicLow,
325 None,
326 &ctx.accounts.project,
327 ctx.accounts.authority.key(),
328 &ctx.accounts.payer,
329 &ctx.accounts.vault,
330 &ctx.accounts.delegate_authority,
331 &ctx.accounts.system_program,
332 &ctx.accounts.instructions_sysvar,
333 ID,
334 false,
335 )?;
336
337 if ctx.accounts.project.subsidize_fees {
338 instructions::refund(
339 0,
340 &ctx.accounts.project,
341 &ctx.accounts.payer,
342 &ctx.accounts.instructions_sysvar,
343 )?;
344 }
345
346 Ok(())
347 }
348
349 pub fn new_user_with_profile(
351 mut ctx: Context<NewUserWithProfile>,
352 args: NewUserWithProfileArgs,
353 ) -> Result<()> {
354 assertions::assert_global_driver(&ctx.accounts.global, &ctx.accounts.authority)?;
355 instructions::new_user_with_profile(&mut ctx, args)?;
356
357 instructions::platform_gate_fn(
358 SerializableActions::PublicLow,
359 None,
360 &ctx.accounts.project,
361 ctx.accounts.authority.key(),
362 &ctx.accounts.payer,
363 &ctx.accounts.vault,
364 &None,
365 &ctx.accounts.system_program,
366 &ctx.accounts.instructions_sysvar,
367 ID,
368 false,
369 )?;
370
371 if ctx.accounts.project.subsidize_fees {
372 instructions::refund(
373 0,
374 &ctx.accounts.project,
375 &ctx.accounts.payer,
376 &ctx.accounts.instructions_sysvar,
377 )?;
378 }
379
380 Ok(())
381 }
382
383 pub fn verify_profile<'info>(
384 ctx: Context<'_, '_, '_, 'info, VerifyProfile<'info>>,
385 args: VerifyProfileArgs,
386 ) -> Result<()> {
387 instructions::verify_profile(ctx, args)
388 }
389
390 pub fn populate_user(ctx: Context<NewUser>, user: User) -> Result<u64> {
393 assertions::assert_global_driver(&ctx.accounts.global, &ctx.accounts.authority)?;
394 instructions::populate_user(ctx, user)
395 }
396
397 pub fn update_user_brutally<'info>(
399 ctx: Context<'_, '_, '_, 'info, UpdateUser<'info>>,
400 args: UpdateUserBrutallyArgs,
401 ) -> Result<()> {
402 assertions::assert_global_driver(&ctx.accounts.global, &ctx.accounts.authority)?;
403 instructions::update_user_brutally(ctx, args)
404 }
405
406 pub fn populate_profile(ctx: Context<NewProfile>, profile: Profile) -> Result<()> {
407 assertions::assert_global_driver(&ctx.accounts.global, &ctx.accounts.authority)?;
408 instructions::populate_profile(ctx, profile)
409 }
410
411 pub fn update_profile_brutally<'info>(
413 ctx: Context<'_, '_, '_, 'info, UpdateProfile<'info>>,
414 args: UpdateProfileBrutallyArgs,
415 ) -> Result<()> {
416 assertions::assert_global_driver(&ctx.accounts.global, &ctx.accounts.authority)?;
417 instructions::update_profile_brutally(ctx, args)
418 }
419
420 pub fn populate_user_with_profile(
422 ctx: Context<NewUserWithProfile>,
423 args: PopulateUserWithProfileArgs,
424 ) -> Result<()> {
425 assertions::assert_global_driver(&ctx.accounts.global, &ctx.accounts.authority)?;
426 instructions::populate_user_with_profile(ctx, args)
427 }
428
429 pub fn delete_leaf<'info>(
430 ctx: Context<'_, '_, '_, 'info, DeleteLeaf<'info>>,
431 args: DeleteLeafArgs,
432 ) -> Result<()> {
433 instructions::delete_leaf(ctx, args)
435 }
436
437 pub fn close_user_tree<'info>(ctx: Context<CloseUserTree>) -> Result<()> {
438 instructions::close_user_tree(ctx)
440 }
441
442 pub fn close_profiles_tree<'info>(ctx: Context<CloseProfilesTree>) -> Result<()> {
443 instructions::close_profiles_tree(ctx)
445 }
446
447 pub fn migrate_project<'info>(
448 ctx: Context<MigrateProject>,
449 args: MigrateProjectArgs,
450 ) -> Result<()> {
451 assertions::assert_global_driver(&ctx.accounts.global, &ctx.accounts.authority)?;
452 let mut data = ctx.accounts.project.try_borrow_mut_data()?;
453
454 let project = Project {
455 bump: args.bump,
456 authority: args.authority,
457 key: args.key,
458 driver: args.driver,
459 name: args.name,
460 services: args.services.as_vec(),
461 associated_programs: args.associated_programs.as_vec(),
462 profile_data_config: args.profile_data_config,
463 profile_trees: ControlledMerkleTrees {
464 active: args.profile_trees_active,
465 merkle_trees: args.profile_trees_trees.as_vec(),
466 schema: SchemaContainer::new(Profile::schema()),
467 },
468 badge_criteria: args.badge_criteria.map(|x| x.as_vec()),
469 subsidize_fees: args.subsidize_fees,
470 };
471 project.serialize(&mut *data)?;
472 Ok(())
473 }
474
475 pub fn change_project_authority(ctx: Context<ChangeProjectAuthority>) -> Result<()> {
478 if !Pubkey::from_str("EgukF3ucRRiTzTLQm2Wv9NXJGAXghMaDU7H2dfTfBHom")
479 .unwrap()
480 .eq(ctx.accounts.authority.key)
481 {
482 return Err(HplHiveControlError::ConstAuthorityMismatch.into());
483 }
484 ctx.accounts.project.authority = *ctx.accounts.new_authority.key;
485 Ok(())
486 }
487
488 pub fn close_account(ctx: Context<CloseAccount>) -> Result<()> {
491 if !Pubkey::from_str("EgukF3ucRRiTzTLQm2Wv9NXJGAXghMaDU7H2dfTfBHom")
492 .unwrap()
493 .eq(ctx.accounts.authority.key)
494 {
495 return Err(HplHiveControlError::ConstAuthorityMismatch.into());
496 }
497
498 let lamports = ctx.accounts.account.lamports();
499 **ctx.accounts.account.lamports.borrow_mut() = 0;
500 **ctx.accounts.authority.lamports.borrow_mut() += lamports;
501
502 Ok(())
503 }
504}
505
506#[derive(Accounts)]
507pub struct MigrateProject<'info> {
508 pub global: Box<Account<'info, Global>>,
509
510 #[account(mut)]
512 pub project: AccountInfo<'info>,
513
514 pub authority: Signer<'info>,
515}
516
517#[derive(AnchorSerialize, AnchorDeserialize)]
518pub struct MigrateProjectArgs {
519 pub bump: u8,
520 pub authority: Pubkey,
521 pub key: Pubkey,
522 pub driver: Pubkey,
523 pub name: String,
524 pub services: ShortVec<Service>,
525 pub associated_programs: ShortVec<AssociatedProgram>,
526 pub profile_data_config: ProfileDataConfig,
527 pub profile_trees_active: u8,
528 pub profile_trees_trees: ShortVec<Pubkey>,
529 pub badge_criteria: Option<ShortVec<BadgeCriteria>>,
530 pub subsidize_fees: bool,
531}
532
533#[derive(Accounts)]
534pub struct ChangeProjectAuthority<'info> {
535 #[account(mut)]
537 pub project: Account<'info, Project>,
538
539 pub new_authority: AccountInfo<'info>,
541
542 pub authority: Signer<'info>,
543}
544
545#[derive(Accounts)]
546pub struct CloseAccount<'info> {
547 #[account(mut, owner = crate::id())]
549 pub account: AccountInfo<'info>,
550
551 pub authority: Signer<'info>,
552}