use {
crate::state::*,
anchor_lang::prelude::*,
hpl_utils::{reallocate, Default},
spl_account_compression::Noop,
};
#[derive(Accounts)]
pub struct CreateDelegateAuthority<'info> {
#[account(mut)]
pub project: Account<'info, Project>,
#[account(
init, payer = payer,
space = DelegateAuthority::LEN,
seeds = [b"delegate_authority".as_ref(), project.key().as_ref(), authority.key().as_ref(), delegate.key().as_ref()],
bump
)]
pub delegate_authority: Account<'info, DelegateAuthority>,
pub delegate: AccountInfo<'info>,
pub authority: Signer<'info>,
#[account(mut)]
pub payer: Signer<'info>,
pub rent_sysvar: Sysvar<'info, Rent>,
pub system_program: Program<'info, System>,
pub log_wrapper: Program<'info, Noop>,
pub clock: Sysvar<'info, Clock>,
#[account(mut)]
pub vault: AccountInfo<'info>,
}
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct CreateDelegateAuthorityArgs {
pub delegations: Option<Vec<ServiceDelegation>>,
}
pub fn create_delegate_authority(
ctx: Context<CreateDelegateAuthority>,
args: CreateDelegateAuthorityArgs,
) -> Result<()> {
let delegate_authority = &mut ctx.accounts.delegate_authority;
delegate_authority.set_defaults();
delegate_authority.bump = ctx.bumps["delegate_authority"];
delegate_authority.project = ctx.accounts.project.key();
delegate_authority.authority = ctx.accounts.delegate.key();
if let Some(delegations) = args.delegations {
if delegations.len() > 0 {
reallocate(
delegations.len() as isize * ServiceDelegation::LEN as isize,
delegate_authority.to_account_info(),
ctx.accounts.payer.to_account_info(),
&ctx.accounts.rent_sysvar,
&ctx.accounts.system_program,
)?;
delegate_authority.delegations = delegations;
}
}
Event::new_delegate_authority(
delegate_authority.key(),
&delegate_authority,
&ctx.accounts.clock,
)
.wrap(ctx.accounts.log_wrapper.to_account_info())?;
Ok(())
}
#[derive(Accounts)]
pub struct ModifyDelegate<'info> {
#[account(mut)]
pub project: Account<'info, Project>,
#[account(mut)]
pub delegate_authority: Account<'info, DelegateAuthority>,
pub authority: Signer<'info>,
#[account(mut)]
pub payer: Signer<'info>,
pub rent_sysvar: Sysvar<'info, Rent>,
pub system_program: Program<'info, System>,
pub log_wrapper: Program<'info, Noop>,
pub clock: Sysvar<'info, Clock>,
#[account(mut)]
pub vault: AccountInfo<'info>,
}
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub struct AddRemoveDelegationArgs {
pub delegation: Option<ServiceDelegation>,
pub index: Option<u8>,
}
pub fn add_remove_delegation(
ctx: Context<ModifyDelegate>,
args: AddRemoveDelegationArgs,
) -> Result<()> {
let delegate_authority = &mut ctx.accounts.delegate_authority;
if let Some(service) = args.delegation {
delegate_authority.delegations.push(service);
reallocate(
ServiceDelegation::LEN as isize,
delegate_authority.to_account_info(),
ctx.accounts.payer.to_account_info(),
&ctx.accounts.rent_sysvar,
&ctx.accounts.system_program,
)?;
} else if let Some(index) = args.index {
delegate_authority.delegations.remove(index as usize);
reallocate(
ServiceDelegation::LEN as isize * -1,
delegate_authority.to_account_info(),
ctx.accounts.payer.to_account_info(),
&ctx.accounts.rent_sysvar,
&ctx.accounts.system_program,
)?;
}
Event::update_delegate_authority(
delegate_authority.key(),
&delegate_authority,
&ctx.accounts.clock,
)
.wrap(ctx.accounts.log_wrapper.to_account_info())?;
Ok(())
}