Created
December 4, 2024 20:06
-
-
Save Benhawkins18/439849101cbc2e1c956aaa9b7b976237 to your computer and use it in GitHub Desktop.
using the error log from validator start up, dust accounts with SOL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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