Created
July 24, 2025 19:40
-
-
Save ngundotra/91ed675009b36eb7ea1aa333d9a16b1d to your computer and use it in GitHub Desktop.
Solana Transfer Test (Priority Fee)
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
| import { | |
| Connection, | |
| Keypair, | |
| PublicKey, | |
| Transaction, | |
| ComputeBudgetProgram, | |
| sendAndConfirmTransaction, | |
| VersionedTransaction, | |
| TransactionMessage | |
| } from '@solana/web3.js'; | |
| import { | |
| createTransferInstruction, | |
| getAssociatedTokenAddress, | |
| getAccount, | |
| TOKEN_PROGRAM_ID | |
| } from '@solana/spl-token'; | |
| import fs from 'fs'; | |
| import path from 'path'; | |
| import os from 'os'; | |
| const USDC_MINT_MAINNET = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'); | |
| const USDC_DECIMALS = 6; | |
| const BASE_TRANSFER_AMOUNT = 0.001; // 0.001 USDC base amount | |
| const TRANSACTIONS_PER_PRIORITY = 10; | |
| interface TransferResult { | |
| signature: string; | |
| priorityFee: number; | |
| landed: boolean; | |
| error?: string; | |
| timestamp: number; | |
| amount: number; | |
| confirmationTime?: number; | |
| } | |
| interface PriorityStats { | |
| priorityFee: number; | |
| sent: number; | |
| landed: number; | |
| landingRate: number; | |
| avgConfirmationTime: number; | |
| } | |
| async function loadKeypair(): Promise<Keypair> { | |
| const keypairPath = path.join(os.homedir(), '.config', 'solana', 'id.json'); | |
| const keypairData = JSON.parse(fs.readFileSync(keypairPath, 'utf-8')); | |
| return Keypair.fromSecretKey(new Uint8Array(keypairData)); | |
| } | |
| async function createTransferTransaction( | |
| connection: Connection, | |
| payer: Keypair, | |
| sourceAta: PublicKey, | |
| destinationAta: PublicKey, | |
| priorityFeePerCu: number, | |
| transferAmount: number | |
| ): Promise<Transaction> { | |
| const transaction = new Transaction(); | |
| // Add compute budget instructions if priority fee > 0 | |
| if (priorityFeePerCu > 0) { | |
| transaction.add( | |
| ComputeBudgetProgram.setComputeUnitPrice({ | |
| microLamports: priorityFeePerCu | |
| }) | |
| ); | |
| transaction.add( | |
| ComputeBudgetProgram.setComputeUnitLimit({ | |
| units: 7000 | |
| }) | |
| ); | |
| } | |
| // Add transfer instruction | |
| transaction.add( | |
| createTransferInstruction( | |
| sourceAta, | |
| destinationAta, | |
| payer.publicKey, | |
| Math.floor(transferAmount * Math.pow(10, USDC_DECIMALS)), | |
| [], | |
| TOKEN_PROGRAM_ID | |
| ) | |
| ); | |
| // Get recent blockhash | |
| const { blockhash } = await connection.getLatestBlockhash(); | |
| transaction.recentBlockhash = blockhash; | |
| transaction.feePayer = payer.publicKey; | |
| return transaction; | |
| } | |
| async function sendTransactionAsync( | |
| connection: Connection, | |
| transaction: Transaction, | |
| payer: Keypair, | |
| priorityFee: number, | |
| transferAmount: number | |
| ): Promise<TransferResult> { | |
| const startTime = Date.now(); | |
| try { | |
| // Sign and send the transaction | |
| transaction.sign(payer); | |
| const signature = await connection.sendRawTransaction(transaction.serialize(), { | |
| skipPreflight: false, | |
| preflightCommitment: 'processed' | |
| }); | |
| // Wait for confirmation | |
| const confirmation = await connection.confirmTransaction(signature, 'confirmed'); | |
| const confirmationTime = Date.now() - startTime; | |
| if (confirmation.value.err) { | |
| return { | |
| signature, | |
| priorityFee, | |
| landed: false, | |
| error: JSON.stringify(confirmation.value.err), | |
| timestamp: Date.now(), | |
| amount: transferAmount | |
| }; | |
| } | |
| return { | |
| signature, | |
| priorityFee, | |
| landed: true, | |
| timestamp: Date.now(), | |
| amount: transferAmount, | |
| confirmationTime | |
| }; | |
| } catch (error: any) { | |
| return { | |
| signature: '', | |
| priorityFee, | |
| landed: false, | |
| error: error.message || 'Unknown error', | |
| timestamp: Date.now(), | |
| amount: transferAmount | |
| }; | |
| } | |
| } | |
| async function main() { | |
| console.log('π Starting USDC transfer comparison with different priority fees...'); | |
| console.log('π Testing 0 vs 500 vs 1000 microlamports/CU with simultaneous sends\n'); | |
| const connection = new Connection('https://api.mainnet-beta.solana.com/6da7c9d2-7d3d-4f7f-8302-97f5fadb58a8', 'confirmed'); | |
| const payer = await loadKeypair(); | |
| console.log(`Wallet: ${payer.publicKey.toBase58()}`); | |
| // Get token accounts | |
| const sourceAta = await getAssociatedTokenAddress( | |
| USDC_MINT_MAINNET, | |
| payer.publicKey | |
| ); | |
| // Check balance | |
| try { | |
| const tokenAccount = await getAccount(connection, sourceAta); | |
| const balance = Number(tokenAccount.amount) / Math.pow(10, USDC_DECIMALS); | |
| console.log(`USDC Balance: ${balance} USDC`); | |
| const maxTransferAmount = BASE_TRANSFER_AMOUNT * 1.1; // Max is 10% more than base | |
| const requiredBalance = maxTransferAmount * TRANSACTIONS_PER_PRIORITY * 3; // 3 priority levels | |
| if (balance < requiredBalance) { | |
| console.error(`Insufficient balance. Need at least ${requiredBalance.toFixed(4)} USDC`); | |
| return; | |
| } | |
| } catch (error) { | |
| console.error('Failed to get USDC balance. Make sure you have USDC in your wallet.'); | |
| return; | |
| } | |
| const priorityFees = [0, 500, 1000]; // microlamports per CU | |
| const results: TransferResult[] = []; | |
| console.log('\nπ Starting simultaneous transfers...\n'); | |
| for (let i = 0; i < TRANSACTIONS_PER_PRIORITY; i++) { | |
| console.log(`Round ${i + 1}/${TRANSACTIONS_PER_PRIORITY}:`); | |
| // Create transactions for both priority levels | |
| const transactionPromises = priorityFees.map(async (priorityFee) => { | |
| // Generate random transfer amount (0.0009 to 0.0011 USDC) | |
| const randomVariation = (Math.random() * 0.2 - 0.1) * BASE_TRANSFER_AMOUNT; | |
| const transferAmount = BASE_TRANSFER_AMOUNT + randomVariation; | |
| // Create transaction | |
| const transaction = await createTransferTransaction( | |
| connection, | |
| payer, | |
| sourceAta, | |
| sourceAta, // Self-transfer | |
| priorityFee, | |
| transferAmount | |
| ); | |
| // Send transaction asynchronously | |
| return sendTransactionAsync(connection, transaction, payer, priorityFee, transferAmount); | |
| }); | |
| // Send both transactions simultaneously | |
| const roundResults = await Promise.all(transactionPromises); | |
| results.push(...roundResults); | |
| // Log results for this round | |
| roundResults.forEach(result => { | |
| if (result.landed) { | |
| console.log(` β ${result.priorityFee} microlamports: ${result.signature} (${result.confirmationTime}ms)`); | |
| } else { | |
| console.log(` β ${result.priorityFee} microlamports: Failed - ${result.error}`); | |
| } | |
| }); | |
| console.log(''); | |
| // Small delay between rounds | |
| await new Promise(resolve => setTimeout(resolve, 1000)); | |
| } | |
| // Calculate and display statistics | |
| console.log('\nπ RESULTS SUMMARY\n' + '='.repeat(50)); | |
| const stats: PriorityStats[] = priorityFees.map(fee => { | |
| const feeResults = results.filter(r => r.priorityFee === fee); | |
| const landed = feeResults.filter(r => r.landed); | |
| const avgTime = landed.length > 0 | |
| ? landed.reduce((sum, r) => sum + (r.confirmationTime || 0), 0) / landed.length | |
| : 0; | |
| return { | |
| priorityFee: fee, | |
| sent: feeResults.length, | |
| landed: landed.length, | |
| landingRate: (landed.length / feeResults.length) * 100, | |
| avgConfirmationTime: avgTime / 1000 // Convert to seconds | |
| }; | |
| }); | |
| stats.forEach(stat => { | |
| console.log(`\nPriority Fee: ${stat.priorityFee} microlamports/CU`); | |
| console.log(` Sent: ${stat.sent}`); | |
| console.log(` Landed: ${stat.landed}`); | |
| console.log(` Landing Rate: ${stat.landingRate.toFixed(2)}%`); | |
| console.log(` Avg Confirmation Time: ${stat.avgConfirmationTime.toFixed(2)}s`); | |
| }); | |
| // Save detailed results | |
| const resultsFile = 'transfer-results.json'; | |
| fs.writeFileSync(resultsFile, JSON.stringify({ stats, results }, null, 2)); | |
| console.log(`\nπΎ Detailed results saved to ${resultsFile}`); | |
| } | |
| main().catch(console.error); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment