Skip to content

Instantly share code, notes, and snippets.

@Benhawkins18
Created December 4, 2024 20:06
Show Gist options
  • Select an option

  • Save Benhawkins18/439849101cbc2e1c956aaa9b7b976237 to your computer and use it in GitHub Desktop.

Select an option

Save Benhawkins18/439849101cbc2e1c956aaa9b7b976237 to your computer and use it in GitHub Desktop.
using the error log from validator start up, dust accounts with SOL
const fs = require("fs");
const solanaWeb3 = require("@solana/web3.js");
// Solana RPC endpoint
const RPC_URL = "https://api.devnet.com";
const connection = new solanaWeb3.Connection(RPC_URL);
// Load source keypair
const SOURCE_KEYPAIR_PATH = "DustwpCnsXvtmr5Z9zRfh1E1rx2deLJJhRRqmFSKPXgh.json";
const secretKey = JSON.parse(fs.readFileSync(SOURCE_KEYPAIR_PATH, "utf8"));
const sourceKeypair = solanaWeb3.Keypair.fromSecretKey(new Uint8Array(secretKey));
// Input and tracking files
const INPUT_FILE = "devnet-rent-paying.log";
const SUCCESSFUL_ACCOUNTS_FILE = "successful_accounts.json";
// Parse accounts from the input file
function parseAccounts(filePath) {
const accounts = [];
const lines = fs.readFileSync(filePath, "utf8").split("\n");
for (const line of lines) {
if (line.includes("rent paying account")) {
const [, account, lamports] = line.split(",");
accounts.push({ account: account.trim(), lamports: Math.floor(parseInt(lamports.trim(), 10)*1.06) });
}
}
return accounts;
}
// Load successful accounts from the tracking file
function loadSuccessfulAccounts() {
if (fs.existsSync(SUCCESSFUL_ACCOUNTS_FILE)) {
const lines = fs.readFileSync(SUCCESSFUL_ACCOUNTS_FILE, "utf8").split("\n").filter(Boolean); // Remove empty lines
return new Set(lines);
}
return new Set();
}
// Append a successful account to the tracking file
function saveSuccessfulAccount(account) {
fs.appendFileSync(SUCCESSFUL_ACCOUNTS_FILE, account + "\n");
}
// Send lamports to the specified account
async function sendLamports(account, lamports) {
try {
const destinationPubkey = new solanaWeb3.PublicKey(account);
const transaction = new solanaWeb3.Transaction().add(
solanaWeb3.SystemProgram.transfer({
fromPubkey: sourceKeypair.publicKey,
toPubkey: destinationPubkey,
lamports: lamports,
})
);
const signature = await solanaWeb3.sendAndConfirmTransaction(
connection,
transaction,
[sourceKeypair]
);
console.log(`Transaction successful: ${signature}`);
return true;
} catch (error) {
console.error(`Failed to send lamports to ${account}:`, error.message);
return false;
}
}
async function rateLimitedProcess(unprocessedAccounts) {
const maxConcurrent = 80; // Max number of concurrent transactions
const worker_start_up_delay = 200
const worker_request_delay = 100
let index = 0;
// Function to process a single account
async function processAccount(workerId) {
while (index < unprocessedAccounts.length) {
const currentIndex = index++;
const { account, lamports } = unprocessedAccounts[currentIndex];
console.log(`Worker ${workerId}: Sending ${lamports} lamports (${lamports / 1e9} SOL) to ${account}...`);
const result = await sendLamports(account, lamports);
if (result) {
saveSuccessfulAccount(account);
} else {
console.error(`Worker ${workerId}: Failed to process ${account}. Will retry later.`);
}
// Enforce .1 second delay for rate limiting on each worker.
await new Promise(resolve => setTimeout(resolve, worker_request_delay));
}
}
// Start workers with staggered 0.2-second delays
const workers = Array.from({ length: maxConcurrent }, (_, i) =>
new Promise(resolve => {
setTimeout(async () => {
await processAccount(i);
resolve();
}, worker_start_up_delay * i);
})
);
// Wait for all workers to complete
await Promise.all(workers);
console.log("All workers completed.");
}
// Main function
async function main() {
const accounts = parseAccounts(INPUT_FILE);
const successfulAccounts = loadSuccessfulAccounts();
const unprocessedAccounts = accounts.filter(({ account }) => !successfulAccounts.has(account));
const totalLamports = unprocessedAccounts.reduce((sum, { lamports }) => sum + lamports, 0);
const totalSol = totalLamports / 1e9;
console.log(`Total lamports needed for unprocessed accounts: ${totalLamports} (${totalSol} SOL)`);
await rateLimitedProcess(unprocessedAccounts);
console.log("Processing complete. Check successful_accounts.json for results.");
}
main().catch((error) => console.error("Error in main function:", error));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment