UNPKG

jito-distributor-sdk

Version:

TypeScript SDK for JITO Merkle Distributor with production-ready versioning and double-hashing support

147 lines (121 loc) • 5.81 kB
import { config } from 'dotenv'; import { Connection, Keypair, PublicKey } from '@solana/web3.js'; import { AnchorProvider, Wallet } from '@coral-xyz/anchor'; import { getAssociatedTokenAddress, transfer, getAccount } from '@solana/spl-token'; import bs58 from 'bs58'; import fs from 'fs'; // Load environment variables config(); async function fundDistributorV6() { console.log('šŸ’° Funding Merkle Distributor V6 with 1 USDC\n'); // Load distributor info let distributorInfo: any; try { const infoFile = fs.readFileSync('./distributor-v6-fixed-v2-info.json', 'utf-8'); distributorInfo = JSON.parse(infoFile); } catch (error) { throw new Error('Could not load distributor-v6-fixed-v2-info.json. Make sure you have created the V6 distributor first.'); } // Validate environment variables const privateKey = process.env.PRIVATE_KEY; const rpcEndpoint = process.env.RPC_ENDPOINT || 'https://mainnet.helius-rpc.com/?api-key=616ef0ca-f8ff-499b-8ca2-cd967fb07ef2'; const walletAddress = process.env.WALLET_ADDRESS || "CoJebSiqLWbXmSCmSSis8NSjva4ag93isJV7dxcz8x5q"; if (!privateKey) { throw new Error('PRIVATE_KEY not found in environment variables'); } console.log('šŸ“‹ Configuration:'); console.log(`RPC Endpoint: ${rpcEndpoint}`); console.log(`Wallet Address: ${walletAddress}`); console.log(`Distributor PDA: ${distributorInfo.distributorPDA}`); console.log(`Mint: ${distributorInfo.mint}`); console.log(`Version: ${distributorInfo.version} (V6 - FIXED V2)`); // Setup connection and wallet const connection = new Connection(rpcEndpoint, 'confirmed'); const keypair = Keypair.fromSecretKey(bs58.decode(privateKey)); const wallet = new Wallet(keypair); console.log(`\nšŸ”‘ Connected wallet: ${wallet.publicKey.toString()}`); if (wallet.publicKey.toString() !== walletAddress) { throw new Error('Wallet address mismatch! Check your PRIVATE_KEY and WALLET_ADDRESS'); } const distributorPDA = new PublicKey(distributorInfo.distributorPDA); const mint = new PublicKey(distributorInfo.mint); // Get token accounts const sourceTokenAccount = await getAssociatedTokenAddress(mint, wallet.publicKey); const distributorTokenVault = await getAssociatedTokenAddress( mint, distributorPDA, true // allowOwnerOffCurve ); console.log('\nšŸ’° Token Account Details:'); console.log(` Source (Your Wallet): ${sourceTokenAccount.toString()}`); console.log(` Destination (Distributor Vault): ${distributorTokenVault.toString()}`); // Check current balances try { const sourceAccount = await getAccount(connection, sourceTokenAccount); console.log(` Current Source Balance: ${sourceAccount.amount.toString()} (${Number(sourceAccount.amount) / 1000000} USDC)`); } catch (error) { throw new Error('Source token account does not exist or has no USDC. You need USDC in your wallet to fund the distributor.'); } try { const vaultAccount = await getAccount(connection, distributorTokenVault); console.log(` Current Vault Balance: ${vaultAccount.amount.toString()} (${Number(vaultAccount.amount) / 1000000} USDC)`); } catch (error) { console.log(' Current Vault Balance: 0 USDC (account not initialized yet)'); } const amountToTransfer = 1000000; // 1 USDC (6 decimals) console.log(`\nšŸ“¤ Transferring ${amountToTransfer / 1000000} USDC to distributor vault...`); try { const signature = await transfer( connection, wallet.payer, sourceTokenAccount, distributorTokenVault, wallet.publicKey, amountToTransfer ); console.log(`āœ… Transfer successful!`); console.log(`Transaction signature: ${signature}`); console.log(`View on Solana Explorer: https://explorer.solana.com/tx/${signature}?cluster=mainnet-beta`); // Verify the transfer console.log('\nšŸ” Verifying transfer...'); try { const updatedVaultAccount = await getAccount(connection, distributorTokenVault); console.log(`āœ… Updated Vault Balance: ${updatedVaultAccount.amount.toString()} (${Number(updatedVaultAccount.amount) / 1000000} USDC)`); } catch (error) { console.log('āŒ Could not verify vault balance after transfer'); } try { const updatedSourceAccount = await getAccount(connection, sourceTokenAccount); console.log(`Updated Source Balance: ${updatedSourceAccount.amount.toString()} (${Number(updatedSourceAccount.amount) / 1000000} USDC)`); } catch (error) { console.log('Could not check updated source balance'); } console.log('\nšŸŽ‰ SUCCESS! Distributor V6 is now funded and ready for claims!'); console.log('šŸ“ Next steps:'); console.log(' 1. Run the V6 claim script to test the complete flow'); console.log(' 2. Verify that the claim works without any errors'); console.log(' 3. Celebrate the complete resolution of InvalidProof errors!'); console.log('\nšŸš€ Ready to run: npx ts-node scripts/claim-tokens-v6-fixed.ts'); } catch (error) { console.error('\nāŒ Error funding distributor:', error); if (error instanceof Error) { if (error.message.includes('insufficient funds')) { console.log('\nšŸ’” You need more USDC in your wallet to fund the distributor.'); console.log(' Make sure you have at least 1 USDC in your token account.'); } else if (error.message.includes('TokenAccountNotFoundError')) { console.log('\nšŸ’” Token account issue. This might be normal for a new distributor vault.'); } } throw error; } } // Run the script if (require.main === module) { fundDistributorV6() .then(() => process.exit(0)) .catch((error) => { console.error('Script failed:', error); process.exit(1); }); } export { fundDistributorV6 };