sablier_thread_program/instructions/
thread_delete.rsuse {
crate::{constants::SEED_THREAD, errors::SablierError, state::*},
anchor_lang::{prelude::*, solana_program::system_program},
};
#[derive(Accounts)]
pub struct ThreadDelete<'info> {
pub authority: Signer<'info>,
#[account(mut)]
pub close_to: SystemAccount<'info>,
#[account(mut)]
pub thread: UncheckedAccount<'info>,
}
pub fn handler(ctx: Context<ThreadDelete>) -> Result<()> {
let thread = &ctx.accounts.thread;
let close_to = &ctx.accounts.close_to;
let thread = match Thread::try_deserialize_unchecked(&mut thread.data.borrow_mut().as_ref()) {
Ok(t) => t,
Err(_) => {
msg!("Not a thread or account does not exist");
return Ok(());
}
};
{
let authority_key = ctx.accounts.authority.key;
let thread_key = ctx.accounts.thread.key;
require!(
thread.authority.eq(authority_key) || authority_key.eq(thread_key),
SablierError::InvalidThreadAuthority
);
let thread_account = &ctx.accounts.thread;
{
require!(
thread_account.owner != &system_program::ID && thread_account.lamports() > 0,
SablierError::InvalidThreadAccount
);
require!(
thread_account.owner == &crate::ID,
SablierError::InvalidThreadAccount
);
let default_vec = Vec::new();
let thread_bump = thread.bump.to_le_bytes();
let seed = [
SEED_THREAD,
thread.authority.as_ref(),
thread.id.as_slice(),
thread.domain.as_ref().unwrap_or(&default_vec).as_slice(),
thread_bump.as_ref(),
];
let expected_thread_key = Pubkey::create_program_address(&seed, &crate::ID)
.map_err(|_| SablierError::InvalidThreadAccount)?;
require!(
expected_thread_key == *thread_key,
SablierError::InvalidThreadAccount
);
}
}
{
let thread_account = &ctx.accounts.thread;
let thread_lamports = thread_account.get_lamports();
thread_account.sub_lamports(thread_lamports)?;
close_to.add_lamports(thread_lamports)?;
}
Ok(())
}