Solana CookbookTokens
How to Close Token Accounts
You can close a token account if you don't want to use it anymore. There are two situations:
- Wrapped SOL - Closing converts Wrapped SOL to SOL
- Other Tokens - You can close it only if token account's balance is 0.
import { getCreateAccountInstruction } from "@solana-program/system";import {findAssociatedTokenPda,getCloseAccountInstruction,getCreateAssociatedTokenInstructionAsync,getInitializeMintInstruction,getMintSize,TOKEN_2022_PROGRAM_ADDRESS,} from "@solana-program/token-2022";import {airdropFactory,appendTransactionMessageInstructions,createSolanaRpc,createSolanaRpcSubscriptions,createTransactionMessage,generateKeyPairSigner,getSignatureFromTransaction,lamports,pipe,sendAndConfirmTransactionFactory,setTransactionMessageFeePayerSigner,setTransactionMessageLifetimeUsingBlockhash,signTransactionMessageWithSigners,} from "@solana/kit";const rpc = createSolanaRpc("http://127.0.0.1:8899");const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");/* constants */const MINT_AUTHORITY = await generateKeyPairSigner();const DECIMALS = 9;const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();let { authorityATA } = await setup();const closeTokenAccountIx = getCloseAccountInstruction({account: authorityATA,destination: MINT_AUTHORITY.address,owner: MINT_AUTHORITY,});const transactionMessage = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(MINT_AUTHORITY, tx),(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),(tx) => appendTransactionMessageInstructions([closeTokenAccountIx], tx));const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction,{ commitment: "confirmed" });const txSignature = getSignatureFromTransaction(signedTransaction);console.log("Transaction Signature:", txSignature);/** The setup function initializes the mint and associated token accounts,**/async function setup() {await airdropFactory({ rpc, rpcSubscriptions })({recipientAddress: MINT_AUTHORITY.address,lamports: lamports(1_000_000_000n), // 1 SOLcommitment: "confirmed",});const mint = await generateKeyPairSigner();const space = BigInt(getMintSize());const rent = await rpc.getMinimumBalanceForRentExemption(space).send();// create & initialize mint accountconst createAccountInstruction = getCreateAccountInstruction({payer: MINT_AUTHORITY,newAccount: mint,lamports: rent,space,programAddress: TOKEN_2022_PROGRAM_ADDRESS,});const initializeMintInstruction = getInitializeMintInstruction({mint: mint.address,decimals: DECIMALS,mintAuthority: MINT_AUTHORITY.address,});// create token accountconst [authorityATA] = await findAssociatedTokenPda({mint: mint.address,owner: MINT_AUTHORITY.address,tokenProgram: TOKEN_2022_PROGRAM_ADDRESS,});const crateAuthorityATAInstruction =await getCreateAssociatedTokenInstructionAsync({payer: MINT_AUTHORITY,mint: mint.address,owner: MINT_AUTHORITY.address,});const instructions = [createAccountInstruction,initializeMintInstruction,crateAuthorityATAInstruction,];const transactionMessage = pipe(createTransactionMessage({ version: 0 }),(tx) => setTransactionMessageFeePayerSigner(MINT_AUTHORITY, tx),(tx) =>setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),(tx) => appendTransactionMessageInstructions(instructions, tx));const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signedTransaction,{ commitment: "confirmed" });return {authorityATA,};}
Is this page helpful?