sablier_thread_program/instructions/
thread_delete.rs1use {
2 crate::{constants::SEED_THREAD, errors::SablierError, state::*},
3 anchor_lang::{prelude::*, solana_program::system_program},
4};
5
6#[derive(Accounts)]
8pub struct ThreadDelete<'info> {
9 pub authority: Signer<'info>,
11
12 #[account(mut)]
14 pub close_to: SystemAccount<'info>,
15
16 #[account(mut)]
19 pub thread: UncheckedAccount<'info>,
20}
21
22pub fn handler(ctx: Context<ThreadDelete>) -> Result<()> {
23 let thread = &ctx.accounts.thread;
24 let close_to = &ctx.accounts.close_to;
25
26 let thread = match Thread::try_deserialize_unchecked(&mut thread.data.borrow_mut().as_ref()) {
32 Ok(t) => t,
33 Err(_) => {
34 msg!("Not a thread or account does not exist");
35 return Ok(());
36 }
37 };
38
39 {
41 let authority_key = ctx.accounts.authority.key;
43 let thread_key = ctx.accounts.thread.key;
44
45 require!(
46 thread.authority.eq(authority_key) || authority_key.eq(thread_key),
47 SablierError::InvalidThreadAuthority
48 );
49
50 let thread_account = &ctx.accounts.thread;
52 {
53 require!(
55 thread_account.owner != &system_program::ID && thread_account.lamports() > 0,
56 SablierError::InvalidThreadAccount
57 );
58
59 require!(
61 thread_account.owner == &crate::ID,
62 SablierError::InvalidThreadAccount
63 );
64
65 let default_vec = Vec::new();
67 let thread_bump = thread.bump.to_le_bytes();
68 let seed = [
69 SEED_THREAD,
70 thread.authority.as_ref(),
71 thread.id.as_slice(),
72 thread.domain.as_ref().unwrap_or(&default_vec).as_slice(),
73 thread_bump.as_ref(),
74 ];
75 let expected_thread_key = Pubkey::create_program_address(&seed, &crate::ID)
76 .map_err(|_| SablierError::InvalidThreadAccount)?;
77 require!(
78 expected_thread_key == *thread_key,
79 SablierError::InvalidThreadAccount
80 );
81 }
82 }
83
84 {
86 let thread_account = &ctx.accounts.thread;
87 let thread_lamports = thread_account.get_lamports();
88 thread_account.sub_lamports(thread_lamports)?;
89 close_to.add_lamports(thread_lamports)?;
90 }
91 Ok(())
92}