Avanzado
AvanzadoLos desarrolladores avanzados de Solana pueden recuperar SOL de cuentas de tokens asociadas (ATA) vacías y cerrar cuentas de tokens SPL no utilizadas utilizando JavaScript/TypeScript con las bibliotecas oficiales de Solana. Este proceso manual proporciona el máximo control sobre la limpieza de cuentas de tokens, la recuperación de rentas y la optimización del monedero.
# Web3.js 2.0 (Latest - Recommended)
npm install @solana/web3.js@2
# OR Web3.js 1.x (Stable)
npm install @solana/web3.js@1
# SPL Token Library
npm install @solana/spl-token
# Additional utilities
npm install bs58 bip39 ed25519-hd-keyimport { Connection, Keypair } from '@solana/web3.js';
import bs58 from 'bs58';
const connection = new Connection(
'https://api.mainnet-beta.solana.com'
);
const secretKey = 'YOUR_BASE58_PRIVATE_KEY';
const keypair = Keypair.fromSecretKey(
bs58.decode(secretKey)
);import { Keypair } from '@solana/web3.js';
import * as bip39 from 'bip39';
import { derivePath } from 'ed25519-hd-key';
const mnemonic = 'your twelve word seed phrase';
const seed = await bip39.mnemonicToSeed(mnemonic);
const derivedSeed = derivePath(
"m/44'/501'/0'/0'", seed.toString('hex')
).key;
const keypair = Keypair.fromSeed(derivedSeed);import {
TOKEN_PROGRAM_ID,
getAccount
} from '@solana/spl-token';
async function findAllTokenAccounts(walletAddress) {
// Get all token accounts
const tokenAccounts = await connection.getTokenAccountsByOwner(
walletAddress,
{ programId: TOKEN_PROGRAM_ID }
);
// Categorize accounts
const emptyAccounts = [];
const accountsWithTokens = [];
for (const account of tokenAccounts.value) {
const accountInfo = await getAccount(connection, account.pubkey);
if (accountInfo.amount === 0n) {
emptyAccounts.push(account.pubkey);
} else {
accountsWithTokens.push({
pubkey: account.pubkey,
mint: accountInfo.mint,
amount: accountInfo.amount
});
}
}
return { emptyAccounts, accountsWithTokens };
}import { TOKEN_2022_PROGRAM_ID } from '@solana/spl-token';
// For Token Extensions (Token-2022)
{ programId: TOKEN_2022_PROGRAM_ID }⚠️ ¡NUNCA cierres cuentas con saldos de tokens > 0 - Perderás tokens valiosos para siempre!
import {
createBurnInstruction,
Transaction,
sendAndConfirmTransaction
} from '@solana/spl-token';
async function burnTokens(
tokenAccount, mint, owner, amount
) {
const instruction = createBurnInstruction(
tokenAccount, // Token account
mint, // Mint account
owner, // Owner
amount // Amount to burn
);
const transaction = new Transaction().add(instruction);
return await sendAndConfirmTransaction(
connection, transaction, [ownerKeypair]
);
}Quema tokens de forma permanente, reduciendo el suministro total y preparando las cuentas para el cierre.
async function burnAllTokensInAccounts(accountsWithTokens) {
for (const account of accountsWithTokens) {
console.log(
`Burning {account.amount} tokens from {account.pubkey}`
);
await burnTokens(
account.pubkey,
account.mint,
ownerKeypair.publicKey,
account.amount
);
// Rate limiting
await new Promise(r => setTimeout(r, 2000));
}
}import {
createCloseAccountInstruction
} from '@solana/spl-token';
async function closeEmptyTokenAccount(
tokenAccount, owner, recipient
) {
// CRITICAL: Verify account is empty first
const accountInfo = await getAccount(
connection, tokenAccount
);
if (accountInfo.amount !== 0n) {
throw new Error('Account must be empty!');
}
const instruction = createCloseAccountInstruction(
tokenAccount, // Empty token account
recipient, // SOL recipient
owner // Account owner
);
const transaction = new Transaction().add(instruction);
return await sendAndConfirmTransaction(
connection, transaction, [ownerKeypair]
);
}Cierra cuentas de tokens VACÍAS individuales y recupera 0.002 SOL de renta por cuenta.
async function closeAllEmptyAccounts(emptyAccounts) {
const batchSize = 20; // Max per transaction
const results = [];
for (let i = 0; i < emptyAccounts.length; i += batchSize) {
const batch = emptyAccounts.slice(i, i + batchSize);
const transaction = new Transaction();
// Double-verify all accounts are empty
for (const account of batch) {
const info = await getAccount(connection, account);
if (info.amount !== 0n) {
throw new Error(`Account not empty: {account}`);
}
transaction.add(
createCloseAccountInstruction(
account, recipient, owner
)
);
}
const signature = await sendAndConfirmTransaction(
connection, transaction, [ownerKeypair]
);
results.push(signature);
// Rate limiting
await new Promise(r => setTimeout(r, 1000));
}
return results;
}import { ComputeBudgetProgram } from '@solana/web3.js';
// Add priority fee for faster confirmation
transaction.add(
ComputeBudgetProgram.setComputeUnitPrice({
microLamports: 1000 // 0.000001 SOL
})
);
// Optional: Set compute unit limit
transaction.add(
ComputeBudgetProgram.setComputeUnitLimit({
units: 200000
})
);Las versiones 1.95.6 y 1.95.7 de @solana/web3.js fueron comprometidas. Siempre usa la última versión:
npm install @solana/web3.js@latestPara usuarios que no se sienten cómodos con la codificación, las herramientas automatizadas ofrecen alternativas más seguras: