1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use log::info;
use solana_account_decoder::{
    parse_account_data::ParsedAccount, UiAccountData,
};
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_client::rpc_request::TokenAccountsFilter;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::Keypair;
use solana_sdk::signer::Signer;
use solana_sdk::transaction::Transaction;
use spl_token::instruction::close_account;
use std::error::Error;
use std::str::FromStr;
use std::sync::Arc;

use crate::pump::TOKEN_PROGRAM;
use crate::util::env;

pub async fn close_all_atas(
    rpc_client: Arc<RpcClient>,
    keypair: &Keypair,
) -> Result<(), Box<dyn Error>> {
    let atas = rpc_client
        .get_token_accounts_by_owner(
            &keypair.pubkey(),
            TokenAccountsFilter::ProgramId(Pubkey::from_str(TOKEN_PROGRAM)?),
        )
        .await?;
    info!("Total ATAs: {}", atas.len());
    let owner = keypair.pubkey();
    for ata in atas {
        if let UiAccountData::Json(ParsedAccount {
            program: _,
            parsed,
            space: _,
        }) = ata.account.data
        {
            if parsed["info"]["tokenAmount"]["amount"]
                .as_str()
                .expect("amount")
                == "0"
            {
                info!("Closing ATA: {}", ata.pubkey);
                let rpc_client = Arc::new(RpcClient::new(env("RPC_URL")));
                let tx = Transaction::new_signed_with_payer(
                    &[close_account(
                        &Pubkey::from_str(TOKEN_PROGRAM)?,
                        &Pubkey::from_str(&ata.pubkey)?,
                        &owner,
                        &owner,
                        &[&owner],
                    )?],
                    Some(&owner),
                    &[keypair],
                    rpc_client.get_latest_blockhash().await?,
                );
                let rpc_client = rpc_client.clone();
                tokio::spawn(async move {
                    rpc_client.send_transaction(&tx).await.unwrap();
                });
            }
        }
    }

    Ok(())
}