Skip to content

Commit

Permalink
feat: add pubkey config struct
Browse files Browse the repository at this point in the history
  • Loading branch information
beeman committed Oct 20, 2024
1 parent 8a35181 commit 27c9740
Show file tree
Hide file tree
Showing 62 changed files with 2,182 additions and 621 deletions.
1 change: 1 addition & 0 deletions anchor/programs/pubkey-protocol/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub const PREFIX: &[u8] = b"pubkey_protocol";

pub const COMMUNITY: &[u8] = b"community";
pub const CONFIG: &[u8] = b"config";
pub const PROFILE: &[u8] = b"profile";
pub const POINTER: &[u8] = b"pointer";

Expand Down
14 changes: 12 additions & 2 deletions anchor/programs/pubkey-protocol/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ pub enum ProtocolError {
InvalidAccountOwner,
#[msg("Account too large")]
AccountTooLarge,
#[msg("Account unauthorized to perform this action")]
UnAuthorized,
#[msg("Authority already exists")]
AuthorityAlreadyExists,
#[msg("Authority does not exist")]
AuthorityNonExistent,
#[msg("Invalid Avatar Url")]
InvalidAvatarURL,
#[msg("Invalid Community Authority")]
InvalidCommunityAuthority,
#[msg("Invalid Discord ID")]
InvalidDiscordID,
#[msg("Invalid Discord URL")]
Expand Down Expand Up @@ -74,6 +74,16 @@ pub enum ProtocolError {
ProviderAlreadyExists,
#[msg("Provider does not exist")]
ProviderDoesNotExist,
#[msg("Signer already exists")]
SignerAlreadyExists,
#[msg("Signer does not exist")]
SignerDoesNotExist,
#[msg("At least one signer is required")]
SignerRequired,
#[msg("Account unauthorized to perform this action")]
UnAuthorized,
#[msg("Unauthorized community action")]
UnauthorizedCommunityAction,
#[msg("Account is not defined in config.community_authority")]
UnAuthorizedCommunityAuthority,
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::state::*;
pub struct CommunityCreate<'info> {
#[account(
init,
payer = fee_payer,
payer = community_authority,
space = Community::size(&[authority.key()], &[]),
seeds = [
PREFIX,
Expand All @@ -19,21 +19,22 @@ pub struct CommunityCreate<'info> {
bump
)]
pub community: Account<'info, Community>,
pub authority: Signer<'info>,

#[account(mut)]
pub config: Account<'info, Config>,
#[account(
mut,
constraint = fee_payer.key().ne(&authority.key()) @ ProtocolError::InvalidFeePayer
constraint = config.check_for_community_authority(&community_authority.key()) @ ProtocolError::UnAuthorizedCommunityAuthority
)]
pub fee_payer: Signer<'info>,
pub community_authority: Signer<'info>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}

pub fn community_create(ctx: Context<CommunityCreate>, args: CommunityCreateArgs) -> Result<()> {
let community = &mut ctx.accounts.community;

let authority = ctx.accounts.authority.key();
let fee_payer = ctx.accounts.fee_payer.key();

// Creating community account
let CommunityCreateArgs {
Expand All @@ -46,7 +47,7 @@ pub fn community_create(ctx: Context<CommunityCreate>, args: CommunityCreateArgs
authority,
avatar_url,
bump: ctx.bumps.community,
fee_payers: vec![fee_payer],
signers: vec![authority],
name,
pending_authority: None,
providers: vec![IdentityProvider::Solana],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use crate::state::*;
use crate::utils::*;

#[derive(Accounts)]
#[instruction(args: UpdateFeePayersArgs)]
pub struct UpdateFeePayers<'info> {
#[instruction(args: CommunitySignerAddArgs)]
pub struct CommunitySignerAdd<'info> {
#[account(
mut,
seeds = [
Expand All @@ -29,18 +29,27 @@ pub struct UpdateFeePayers<'info> {
pub system_program: Program<'info, System>,
}

pub fn community_update_feepayers(
ctx: Context<UpdateFeePayers>,
args: UpdateFeePayersArgs,
pub fn community_signer_add(
ctx: Context<CommunitySignerAdd>,
args: CommunitySignerAddArgs,
) -> Result<()> {
let community = &mut ctx.accounts.community;
let new_fee_payers = args.new_fee_payers;
let signer = args.signer;

// Update the fee_payers vector
community.fee_payers = new_fee_payers;
// Check if the signer is already in the community.signers vector
require!(
!community.signers.contains(&signer),
ProtocolError::SignerAlreadyExists
);

// Add the signer to the community.signers vector
community.signers.push(signer);

// Sort the signers vector
community.signers.sort();

// Calculate the new account size
let new_account_size = Community::size(&community.fee_payers, &community.providers);
let new_account_size = Community::size(&community.signers, &community.providers);

// Reallocate the account if necessary
realloc_account(
Expand All @@ -57,6 +66,6 @@ pub fn community_update_feepayers(
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct UpdateFeePayersArgs {
pub new_fee_payers: Vec<Pubkey>,
pub struct CommunitySignerAddArgs {
pub signer: Pubkey,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use anchor_lang::prelude::*;

use crate::constants::*;
use crate::errors::*;
use crate::state::*;
use crate::utils::*;

#[derive(Accounts)]
#[instruction(args: CommunitySignerRemoveArgs)]
pub struct CommunitySignerRemove<'info> {
#[account(
mut,
seeds = [
PREFIX,
COMMUNITY,
&community.slug.as_bytes()
],
bump = community.bump,
has_one = authority @ ProtocolError::UnAuthorized,
)]
pub community: Account<'info, Community>,

#[account(
mut,
constraint = community.check_for_authority(&authority.key()) @ ProtocolError::UnAuthorized)
]
pub authority: Signer<'info>,

pub system_program: Program<'info, System>,
}

pub fn community_signer_remove(
ctx: Context<CommunitySignerRemove>,
args: CommunitySignerRemoveArgs,
) -> Result<()> {
let community = &mut ctx.accounts.community;
let signer = args.signer;

// Ensure the signer is in the community.signers vector
require!(
community.signers.contains(&signer),
ProtocolError::SignerDoesNotExist
);

// Ensure there is at least one signer left after removing this signer
require!(community.signers.len() > 1, ProtocolError::SignerRequired);

// Remove the signer from the community.signers vector
community.signers.retain(|s| !s.eq(&signer));

// Calculate the new account size
let new_account_size = Community::size(&community.signers, &community.providers);

// Reallocate the account if necessary
realloc_account(
community.to_account_info(),
new_account_size,
ctx.accounts.authority.to_account_info(),
ctx.accounts.system_program.to_account_info(),
)?;

// Validate the updated community
community.validate()?;

Ok(())
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct CommunitySignerRemoveArgs {
pub signer: Pubkey,
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
pub mod community_create;
pub mod community_provider_disable;
pub mod community_provider_enable;
pub mod community_signer_add;
pub mod community_signer_remove;
pub mod community_update_authority_approve;
pub mod community_update_authority_decline;
pub mod community_update_authority_request;
pub mod community_update_details;
pub mod community_update_feepayers;
pub mod verify_profile_identity;

pub use community_create::*;
pub use community_provider_disable::*;
pub use community_provider_enable::*;
pub use community_signer_add::*;
pub use community_signer_remove::*;
pub use community_update_authority_approve::*;
pub use community_update_authority_decline::*;
pub use community_update_authority_request::*;
pub use community_update_details::*;
pub use community_update_feepayers::*;
pub use verify_profile_identity::*;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use anchor_lang::prelude::*;

use crate::constants::*;
use crate::state::*;

#[derive(Accounts)]
#[instruction(args: ConfigInitArgs)]
pub struct ConfigInit<'info> {
#[account(
init,
payer = authority,
space = Config::size(),
seeds = [ PREFIX, CONFIG ],
bump
)]
pub config: Account<'info, Config>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}

pub fn config_init(ctx: Context<ConfigInit>, args: ConfigInitArgs) -> Result<()> {
let config = &mut ctx.accounts.config;

let authority = ctx.accounts.authority.key();

config.set_inner(Config {
bump: ctx.bumps.config,
community_authority: args.community_authority,
config_authority: authority,
});

config.validate()?;

Ok(())
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct ConfigInitArgs {
pub community_authority: Pubkey,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod config_init;

pub use config_init::*;
2 changes: 2 additions & 0 deletions anchor/programs/pubkey-protocol/src/instructions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
pub mod community;
pub mod config;
pub mod identity;
pub mod profile;

pub use community::*;
pub use config::*;
pub use identity::*;
pub use profile::*;
20 changes: 15 additions & 5 deletions anchor/programs/pubkey-protocol/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@ pub mod pubkey_protocol {
) -> Result<()> {
community::community_provider_enable(ctx, args)
}
pub fn community_signer_add(
ctx: Context<CommunitySignerAdd>,
args: CommunitySignerAddArgs,
) -> Result<()> {
community::community_signer_add(ctx, args)
}

pub fn community_signer_remove(
ctx: Context<CommunitySignerRemove>,
args: CommunitySignerRemoveArgs,
) -> Result<()> {
community::community_signer_remove(ctx, args)
}

pub fn community_update_authority_approve(
ctx: Context<CommunityUpdateAuthorityApprove>,
Expand Down Expand Up @@ -98,11 +111,8 @@ pub mod pubkey_protocol {
community::community_update_details(ctx, args)
}

pub fn community_update_feepayers(
ctx: Context<UpdateFeePayers>,
args: UpdateFeePayersArgs,
) -> Result<()> {
community::community_update_feepayers(ctx, args)
pub fn config_init(ctx: Context<ConfigInit>, args: ConfigInitArgs) -> Result<()> {
config::config_init(ctx, args)
}

pub fn verify_profile_identity(
Expand Down
14 changes: 7 additions & 7 deletions anchor/programs/pubkey-protocol/src/state/community.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ pub struct Community {
pub name: String,
// Avatar URL
pub avatar_url: String,
// Fee payers, can be multiple
pub fee_payers: Vec<Pubkey>,
// Signers, can be multiple
pub signers: Vec<Pubkey>,
// Authority that have been delegated to
pub authority: Pubkey,
// Pending authority that must sign to complete
Expand All @@ -33,8 +33,8 @@ pub struct Community {
}

impl Community {
pub fn size(fee_payers: &[Pubkey], providers: &[IdentityProvider]) -> usize {
let fee_payers_size = 4 + (fee_payers.len() * 32);
pub fn size(signers: &[Pubkey], providers: &[IdentityProvider]) -> usize {
let signers_size = 4 + (signers.len() * 32);
let providers_size = 4 + (providers.len() * std::mem::size_of::<IdentityProvider>());
let links_count = 6;
let links_size = (1 + 4 + MAX_URL_SIZE) * links_count;
Expand All @@ -46,15 +46,15 @@ impl Community {
4 + MAX_URL_SIZE +
32 + // authority
1 + 32 + // pending_authority (Option<Pubkey>)
fee_payers_size +
signers_size +
providers_size +
links_size
}

pub fn validate(&self) -> Result<()> {
let avatar_url_len = self.avatar_url.len();
let providers_len = self.providers.len();
let fee_payers_len = self.fee_payers.len();
let signers_len = self.signers.len();

require!(is_valid_username(&self.slug), ProtocolError::InvalidSlug);

Expand All @@ -71,7 +71,7 @@ impl Community {
);

require!(
fee_payers_len <= MAX_VECTOR_SIZE.into(),
signers_len <= MAX_VECTOR_SIZE.into(),
ProtocolError::MaxSizeReached
);

Expand Down
Loading

0 comments on commit 27c9740

Please sign in to comment.