I have created 2 types of Associated Token Account:
1, Use token program:https://solscan.io/tx/3BC6yNwcaandgzSgFX4YP1nYopPLsa9RyRdqi4bDmKLpWsjiRqMKRaQaoZhgbBQpEsMhcFLoZwobKMVZvrLuUi6C
2, Use token 2022 program:https://solscan.io/tx/615Q7tW715HBvLHqnvPUXDX5ELFKgRdHQhNLYegWKHrtpgAp1jv6ccbZPnPtE3R5YPJXTxjfmmGMRpdBMMaFKnVE
I can close ATA in #1 with this code below:
import fs from 'fs';import csv from 'csv-parser';import { createObjectCsvWriter } from 'csv-writer';import { getOrCreateAssociatedTokenAccount, closeAccount } from "@solana/spl-token";import { getExplorerLink } from "@solana-developers/helpers";import { Connection, PublicKey, clusterApiUrl, Keypair } from "@solana/web3.js";import bs58 from "bs58";// Initialize connectionconst connection = new Connection(clusterApiUrl("mainnet-beta"));// Substitute in your token mint accountconst tokenMintAccount = new PublicKey("Bv2ajiWdngTyRFabXCKiwGDJh5SEfJwoRPkkTQ2uf6EE");// CSV writer for failed transactionsconst csvWriter = createObjectCsvWriter({ path: 'failed_send.csv', header: [{ id: 'prvkey', title: 'PrivateKey' }, { id: 'error', title: 'Error' }]});// Function to process each private key with retry logic and close token accountasync function processPrivateKey(privateKeyBase58) { const user = Keypair.fromSecretKey(bs58.decode(privateKeyBase58)); const recipient = user.publicKey; let success = false; let delayTime = 1500; // Start with 1.5 seconds delay for (let attempt = 1; attempt <= 3; attempt++) { try { console.log(`🔑 Attempt ${attempt} for keypair with public key: ${user.publicKey.toBase58()}`); let tokenAccount; try { // Check if the associated token account exists tokenAccount = await getOrCreateAssociatedTokenAccount( connection, user, tokenMintAccount, recipient ); console.log(`Token Account: ${tokenAccount.address.toBase58()}`); } catch (error) { console.error(`Error fetching/creating token account: ${error.message || error}`); throw error; // Re-throw the error to retry } // If token account exists, proceed to close it const closeTx = await closeAccount( connection, user, // payer tokenAccount.address, // address of the token account to be closed recipient, // destination wallet for SOL user // owner of the token account ); const link = getExplorerLink("tx", closeTx,"mainnet-beta" ); console.log(`✅ Closed token Account: ${link}`); success = true; break; } catch (error) { console.error(`Error on attempt ${attempt} for private key ${privateKeyBase58}: ${error.message || error}`); if (error.message.includes("429 Too Many Requests")) { console.log('Hit rate limit, increasing delay...'); } await delay(delayTime); // Wait before retrying delayTime *= 2; // Exponentially increase delay time (1.5s, 3s, 6s, etc.) } } if (!success) { return { prvkey: privateKeyBase58, error: 'Failed after 3 attempts' }; }}// Function to delay for a specified number of millisecondsfunction delay(ms) { return new Promise(resolve => setTimeout(resolve, ms));}// Read the CSV file and process each private key with a delay and retry logic(async () => { const rows = []; const failedKeys = []; fs.createReadStream('key.csv') .pipe(csv()) .on('data', (row) => { rows.push(row); }) .on('end', async () => { console.log('CSV file successfully processed.'); for (const row of rows) { const privateKeyBase58 = row.prvkey; const result = await processPrivateKey(privateKeyBase58); if (result) { failedKeys.push(result); } await delay(1500); // Wait for 1.5 seconds before processing the next key } if (failedKeys.length > 0) { await csvWriter.writeRecords(failedKeys); console.log('Failed private keys have been recorded in failed_tx.csv.'); } console.log('All private keys processed.'); });})();
When I try to close ATA in #2 with change token mint account from Bv2ajiWdngTyRFabXCKiwGDJh5SEfJwoRPkkTQ2uf6EE to BorpaZo2RdiYcriLJu2GRefZdgQPmv63nA8jsVVsMV7W, it shows:
TokenAccountNotFoundError
Please help me!