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
text/typescript
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 };