SOL转账模块

sol转账模块是为了方便项目中多个账号资金管理需求管理多个地址,对同一个项目进行交易,但是不能被平台检测出来这是相关联的地址。通常一些数据平台检测地址是否有关联性,会通过资金来源来识别。这样我们就要避免多个地址的资金来源是同一个地址,或者很容易被发现是来源同一个地址,一般平台只会检测上一层的来

sol转账模块是为了方便项目中多个账号资金管理

需求

管理多个地址,对同一个项目进行交易,但是不能被平台检测出来这是相关联的地址。 通常一些数据平台检测地址是否有关联性,会通过资金来源来识别。这样我们就要避免多个地址的资金来源是同一个地址,或者很容易被发现是来源同一个地址,一般平台只会检测上一层的来源。

解决

我们可以通过中心化交易所,转出到每个链上地址。但是这个缺点很明显,费时费力。 通过代码实现SOL从多个地址一一对应转到多个地址,也就是多转多,为了避免被平台标记为相关地址(老鼠仓),可以多转几层。每次用不同的地址转到不同地址,最后转到我们真正使用的地址上。 由于初始的资金来源还是从一个地址中分发出来的,所以还要实现一转多。

我们先实现余额的查询,批量对多个地址查询(地址来源参考上一篇文章中)

批量查询余额代码
const fs = require('fs-extra');
const path = require('path');

class SolanaBalanceChecker {
    constructor() {
        // 加载环境变量
        try {
            require('dotenv').config();
        } catch (error) {
            console.warn('无法加载dotenv,将使用默认网络配置');
        }

        // 使用环境变量中的RPC URL(如果存在),否则使用默认的API端点
        const rpcUrl = process.env.SOLANA_RPC_URL || clusterApiUrl('mainnet-beta');
        const network = process.env.SOLANA_NETWORK || 'mainnet-beta';

        this.connection = new Connection(rpcUrl, {
            commitment: 'confirmed',
            confirmTransactionInitialTimeout: 60000, // 60秒超时
            disableRetryOnRateLimit: false // 启用速率限制重试
        });

        console.log(`SolanaBalanceChecker初始化完成,使用网络: ${network}`);
        console.log(`RPC URL: ${rpcUrl}`);
    }

    /**
     * 设置网络连接
     * @param {string} network - 网络名称 ('mainnet-beta', 'testnet', 'devnet')
     */
    setNetwork(network) {
        this.connection = new Connection(clusterApiUrl(network), {
            commitment: 'confirmed',
            confirmTransactionInitialTimeout: 60000, // 60秒超时
            disableRetryOnRateLimit: false // 启用速率限制重试
        });
        console.log(`SolanaBalanceChecker网络已切换到: ${network}`);
    }

    /**
     * 查询单个地址的SOL余额
     * @param {string} address - 钱包地址
     * @returns {Promise<number>} - SOL余额
     */
    async checkBalance(address) {
        try {
            console.log(`开始查询地址 ${address} 的SOL余额...`);

            // 验证地址格式
            if (!address || typeof address !== 'string') {
                throw new Error('无效的钱包地址');
            }

            // 尝试创建PublicKey对象,这会验证地址格式
            let publicKey;
            try {
                publicKey = new PublicKey(address);
            } catch (error) {
                throw new Error(`无效的Solana地址格式: ${error.message}`);
            }

            // 使用重试机制查询余额
            let retries = 3;
            let lastError = null;

            while (retries > 0) {
                try {
                    const balance = await this.connection.getBalance(publicKey);
                    const solBalance = balance / LAMPORTS_PER_SOL;
                    console.log(`地址 ${address} 的SOL余额: ${solBalance}`);
                    return solBalance;
                } catch (error) {
                    lastError = error;
                    console.error(`查询余额失败,剩余重试次数: ${retries - 1}, 错误: ${error.message}`);
                    retries--;

                    if (retries > 0) {
                        // 等待一段时间再重试
                        await new Promise(resolve => setTimeout(resolve, 2000));
                    }
                }
            }

            throw new Error(`多次尝试查询余额失败: ${lastError ? lastError.message : '未知错误'}`);
        } catch (error) {
            console.error(`查询SOL余额失败: ${error.message}`);
            throw new Error(`查询SOL余额失败: ${error.message}`);
        }
    }

    /**
     * 批量查询多个地址的SOL余额
     * @param {string[]} addresses - 钱包地址数组
     * @returns {Promise<Object>} - 地址到余额的映射
     */
    async checkMultipleBalances(addresses) {
        try {
            console.log(`开始批量查询 ${addresses.length} 个地址的SOL余额...`);

            // 验证地址格式并创建PublicKey对象数组
            const publicKeys = [];
            const addressMap = {}; // 用于保存PublicKey字符串到原始地址的映射

            for (const address of addresses) {
                if (!address || typeof address !== 'string') {
                    console.warn(`跳过无效地址: ${address}`);
                    continue;
                }

                try {
                    const publicKey = new PublicKey(address);
                    publicKeys.push(publicKey);
                    addressMap[publicKey.toString()] = address; // 保存映射关系
                } catch (error) {
                    console.warn(`跳过无效的Solana地址 ${address}: ${error.message}`);
                }
            }

            if (publicKeys.length === 0) {
                throw new Error('没有有效的地址可供查询');
            }

            // 分批查询,每批最多100个
            const MAX_BATCH_SIZE = 100;
            const balances = {};
            let totalQueried = 0;

            for (let i = 0; i < publicKeys.length; i += MAX_BATCH_SIZE) {
                const batchKeys = publicKeys.slice(i, i + MAX_BATCH_SIZE);

                // 使用重试机制批量查询账户信息
                let retries = 3;
                let lastError = null;
                let accountInfos = null;

                while (retries > 0 && accountInfos === null) {
                    try {
                        // 使用getMultipleAccountsInfo批量查询
                        accountInfos = await this.connection.getMultipleAccountsInfo(batchKeys);
                    } catch (error) {
                        lastError = error;
                        // console.error(`批量查询余额失败,剩余重试次数: ${retries - 1}, 错误: ${error.message}`);
                        console.error(`批量查询失败(第 ${i / MAX_BATCH_SIZE + 1} 批),剩余重试次数: ${retries - 1}, 错误: ${error.message}`);
                        retries--;

                        if (retries > 0) {
                            // 等待一段时间再重试
                            await new Promise(resolve => setTimeout(resolve, 2000));
                        }
                    }
                }

                if (accountInfos === null) {
                    throw new Error(`多次尝试批量查询余额失败: ${lastError ? lastError.message : '未知错误'}`);
                }

                // 处理结果
                publicKeys.forEach((publicKey, index) => {
                    const address = addressMap[publicKey.toString()];
                    const accountInfo = accountInfos[index];

                    // 如果账户存在,lamports属性包含余额
                    // 如果账户不存在,余额为0
                    const lamports = accountInfo ? accountInfo.lamports : 0;
                    const solBalance = lamports / LAMPORTS_PER_SOL;

                    balances[address] = solBalance;
                    totalQueried++;
                });
            }
            console.log(`成功批量查询了 ${totalQueried} 个地址的SOL余额`);
            return balances;
        } catch (error) {
            console.error(`批量查询SOL余额失败: ${error.message}`);
            throw new Error(`批量查询SOL余额失败: ${error.message}`);
        }
    }

    /**
     * 查询钱包文件夹中所有钱包的SOL余额
     * @param {string} folderNum - 钱包文件夹编号
     * @returns {Promise<Array>} - 余额信息数组
     */
    async checkFolderBalance(folderNum) {
        try {
            // 创建主钱包目录 - 修改为与wallet-routes.js一致的路径
            const mainWalletDir = path.join(__dirname, 'web', 'wallets');
            if (!fs.existsSync(mainWalletDir)) {
                fs.mkdirSync(mainWalletDir, { recursive: true });
            }

            // 构建文件夹路径
            const folderName = `wallets${folderNum}`;
            const folderPath = path.join(mainWalletDir, folderName);

            if (!fs.existsSync(folderPath)) {
                throw new Error(`找不到文件夹: ${folderPath}`);
            }

            // 获取所有钱包文件
            const walletFiles = fs.readdirSync(folderPath)
                .filter(file => file.endsWith('.json'))
                .sort();

            if (walletFiles.length === 0) {
                throw new Error(`文件夹 ${folderName} 中没有钱包文件`);
            }

            console.log(`找到 ${walletFiles.length} 个钱包文件,准备批量查询余额...`);

            // 收集所有钱包地址
            const addresses = [];
            const walletDataList = [];

            for (let i = 0; i < walletFiles.length; i++) {
                try {
                    const walletFile = walletFiles[i];
                    const walletPath = path.join(folderPath, walletFile);
                    const walletData = fs.readJsonSync(walletPath);

                    addresses.push(walletData.address);
                    walletDataList.push({
                        index: i + 1,
                        address: walletData.address
                    });
                } catch (error) {
                    console.error(`读取钱包文件 #${i + 1} 失败: ${error.message}`);
                }
            }

            if (addresses.length === 0) {
                throw new Error('没有有效的钱包地址可供查询');
            }

            // 批量查询余额
            const balanceMap = await this.checkMultipleBalances(addresses);

            // 处理结果
            const balances = [];
            let totalBalance = 0;
            let nonZeroWallets = 0;

            for (const walletData of walletDataList) {
                const solBalance = balanceMap[walletData.address] || 0;

                balances.push({
                    index: walletData.index,
                    address: walletData.address,
                    balance: solBalance
                });

                totalBalance += solBalance;
                if (solBalance > 0) {
                    nonZeroWallets++;
                }
            }

            if (balances.length === 0) {
                throw new Error('没有成功查询到任何钱包余额');
            }

            // 返回余额信息和统计数据
            return {
                balances,
                stats: {
                    totalWallets: balances.length,
                    nonZeroWallets,
                    totalBalance,
                    averageBalance: totalBalance / balances.length,
                    nonZeroAverage: nonZeroWallets > 0 ? totalBalance / nonZeroWallets : 0
                }
            };
        } catch (error) {
            throw new Error(`查询SOL余额失败: ${error.message}`);
        }
    }

    /**
     * 查询指定钱包的SOL余额
     * @param {string} folderNum - 钱包文件夹编号
     * @param {number} walletIndex - 钱包索引
     * @returns {Promise<Object>} - 余额信息
     */
    async checkWalletBalance(folderNum, walletIndex) {
        try {
            // 创建主钱包目录 - 修改为与wallet-routes.js一致的路径
            const mainWalletDir = path.join(__dirname, 'web', 'wallets');
            if (!fs.existsSync(mainWalletDir)) {
                fs.mkdirSync(mainWalletDir, { recursive: true });
            }

            // 构建文件夹路径
            const folderName = `wallets${folderNum}`;
            const folderPath = path.join(mainWalletDir, folderName);

            if (!fs.existsSync(folderPath)) {
                throw new Error(`找不到文件夹: ${folderPath}`);
            }

            // 获取所有钱包文件
            const walletFiles = fs.readdirSync(folderPath)
                .filter(file => file.endsWith('.json'))
                .sort();

            if (walletFiles.length === 0) {
                throw new Error(`文件夹 ${folderName} 中没有钱包文件`);
            }

            if (walletIndex < 1 || walletIndex > walletFiles.length) {
                throw new Error(`无效的钱包索引,应为 1 到 ${walletFiles.length}`);
            }

            const walletFile = walletFiles[walletIndex - 1];
            const walletPath = path.join(folderPath, walletFile);
            const walletData = fs.readJsonSync(walletPath);

            // 查询余额
            const publicKey = new PublicKey(walletData.address);
            const balance = await this.connection.getBalance(publicKey);

            return {
                index: walletIndex,
                address: walletData.address,
                balance: balance / LAMPORTS_PER_SOL
            };
        } catch (error) {
            throw new Error(`查询SOL余额失败: ${error.message}`);
        }
    }
}

module.exports = SolanaBalanceChecker;
SOL多转多代码
const bs58 = require('bs58');
const fs = require('fs-extra');
const path = require('path');
const inquirer = require('inquirer');
const ConfigManager = require('./config-manager').default;
const SolanaBalanceChecker = require('./solana-balance-checker');
const SolanaAddressGenerator = require('./solana-address-generator');
const moment = require('moment');
const CryptoJS = require('crypto-js');
const localWallets = require('./solana-wallets');

class SolanaTransfer {
    constructor() {
        this.config = new ConfigManager();
        this.networkUrl = this.config.getNetworkUrl();
        this.connection = new Connection(this.networkUrl);
        this.balanceChecker = new SolanaBalanceChecker();
        this.balanceChecker.connection = this.connection;
        this.addressGenerator = new SolanaAddressGenerator();
        this.minRentExemption = null; // 初始化最小租金豁免金额
        this.feeReserve = 0.001; // 预留的交易费用(SOL)
        this.localWallets = new localWallets();
        this.transferFee = 0.000005; // 转账手续费
    }

    async run() {
        try {
            while (true) {
                const { action } = await inquirer.prompt([
                    {
                        type: 'list',
                        name: 'action',
                        message: 'SOL 转账系统',
                        choices: [
                            { name: '单笔转账', value: '1' },
                            { name: '文件夹间相同编号钱包互转', value: '2' },
                            { name: '一对多转账(相同金额)', value: '3' },
                            { name: '一对多转账(随机金额)', value: '4' },
                            { name: '退出', value: '5' }
                        ],
                        loop: false // 禁用循环滚动
                    }
                ]);

                if (action === '1') {
                    const { fromFolderNum } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'fromFolderNum',
                            message: '请输入发送方文件夹编号:'
                        }
                    ]);

                    const { fromWalletIndex } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'fromWalletIndex',
                            message: '请输入发送方钱包编号:'
                        }
                    ]);

                    const { toFolderNum } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'toFolderNum',
                            message: '请输入接收方文件夹编号:'
                        }
                    ]);

                    const { toWalletIndex } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'toWalletIndex',
                            message: '请输入接收方钱包编号:'
                        }
                    ]);

                    const { amount } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'amount',
                            message: '请输入转账金额 (SOL):'
                        }
                    ]);

                    const { password } = await inquirer.prompt([
                        {
                            type: 'password',
                            name: 'password',
                            message: '请输入钱包密码:',
                            mask: '*'
                        }
                    ]);

                    try {
                        const txHash = await this.transferBetweenWallets(
                            fromFolderNum.trim(),
                            parseInt(fromWalletIndex),
                            toFolderNum.trim(),
                            parseInt(toWalletIndex),
                            parseFloat(amount),
                            password
                        );
                    } catch (error) {
                        console.error(`\n${error.message}`);
                    }
                } else if (action === '2') {
                    const { fromFolderNum } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'fromFolderNum',
                            message: '请输入发送方文件夹编号:'
                        }
                    ]);

                    const { toFolderNum } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'toFolderNum',
                            message: '请输入接收方文件夹编号:'
                        }
                    ]);

                    const { password } = await inquirer.prompt([
                        {
                            type: 'password',
                            name: 'password',
                            message: '请输入钱包密码:',
                            mask: '*'
                        }
                    ]);

                    try {
                        const results = await this.folderToFolderTransfer(fromFolderNum.trim(), toFolderNum.trim(), password);
                        this.displayTransferResults(results);
                    } catch (error) {
                        console.error(`\n错误: ${error.message}`);
                    }
                } else if (action === '3') {
                    const { fromFolderNum } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'fromFolderNum',
                            message: '请输入发送方文件夹编号:'
                        }
                    ]);

                    const { fromWalletIndex } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'fromWalletIndex',
                            message: '请输入发送方钱包编号:'
                        }
                    ]);

                    const { toFolderNum } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'toFolderNum',
                            message: '请输入接收方文件夹编号:'
                        }
                    ]);

                    const { walletRange } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'walletRange',
                            message: '请输入接收方钱包编号范围 (例如: 1-10):'
                        }
                    ]);

                    const rangeParts = walletRange.split('-');
                    if (rangeParts.length !== 2) {
                        console.log('\n无效的范围格式!请使用 "起始-结束" 格式,例如: 1-10');
                        continue;
                    }

                    const toStart = parseInt(rangeParts[0].trim());
                    const toEnd = parseInt(rangeParts[1].trim());

                    if (isNaN(toStart) || isNaN(toEnd) || toStart < 1 || toEnd < toStart) {
                        console.log('\n无效的接收方钱包编号范围!');
                        continue;
                    }

                    const receiverCount = toEnd - toStart + 1;
                    console.log(`\n接收方钱包范围: ${toStart} 到 ${toEnd},共 ${receiverCount} 个钱包`);

                    let amounts = [];
                    if (action === '3') {
                        const { amount } = await inquirer.prompt([
                            {
                                type: 'input',
                                name: 'amount',
                                message: '请输入每个接收方的转账金额(SOL):'
                            }
                        ]);

                        const amountFloat = parseFloat(amount);
                        if (isNaN(amountFloat) || amountFloat <= 0) {
                            console.log('\n请输入有效的正数金额!');
                            continue;
                        }

                        amounts = Array(receiverCount).fill(amountFloat);
                        console.log(`\n每个接收方转账金额: ${amountFloat} SOL`);
                    } else {
                        const { amountList } = await inquirer.prompt([
                            {
                                type: 'input',
                                name: 'amountList',
                                message: '请输入每个接收方的转账金额,用逗号分隔 (例如: 1.5,2.0,1.8):'
                            }
                        ]);

                        amounts = amountList.split(',').map(a => parseFloat(a.trim()));
                        if (amounts.length !== receiverCount) {
                            console.log('\n转账金额数量与接收方数量不匹配!');
                            continue;
                        }

                        if (amounts.some(a => isNaN(a) || a <= 0)) {
                            console.log('\n请确保所有金额都是有效的正数!');
                            continue;
                        }
                    }

                    const totalAmount = amounts.reduce((sum, a) => sum + a, 0);
                    console.log(`\n总转账金额: ${totalAmount} SOL`);

                    const { password } = await inquirer.prompt([
                        {
                            type: 'password',
                            name: 'password',
                            message: '请输入钱包密码:',
                            mask: '*'
                        }
                    ]);

                    try {
                        const results = await this.oneToManyTransferWithAmounts(
                            fromFolderNum.trim(),
                            parseInt(fromWalletIndex),
                            toFolderNum.trim(),
                            toStart,
                            toEnd,
                            amounts,
                            password
                        );
                        this.displayTransferResults(results);
                    } catch (error) {
                        console.error(`\n错误: ${error.message}`);
                    }
                } else if (action === '4') {
                    // 一对多转账(随机金额)
                    const { fromFolderNum } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'fromFolderNum',
                            message: '请输入发送方文件夹编号:'
                        }
                    ]);

                    const { fromWalletIndex } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'fromWalletIndex',
                            message: '请输入发送方钱包编号:'
                        }
                    ]);

                    // 获取发送方钱包地址,用于检查余额
                    try {
                        const { address: fromAddress } = await this.getWalletFromNumber(fromFolderNum.trim(), parseInt(fromWalletIndex));
                        console.log(`\n发送方钱包地址: ${fromAddress}`);

                        // 检查发送方余额
                        const balance = await this.getBalance(fromAddress);
                        console.log(`发送方钱包余额: ${balance} SOL`);

                        if (balance <= 0) {
                            console.log('\n错误: 发送方钱包余额为零,无法进行转账!');
                            continue;
                        }
                    } catch (error) {
                        console.error(`\n错误: 获取发送方钱包信息失败: ${error.message}`);
                        continue;
                    }

                    const { toFolderNum } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'toFolderNum',
                            message: '请输入接收方文件夹编号:'
                        }
                    ]);

                    const { walletRange } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'walletRange',
                            message: '请输入接收方钱包编号范围 (例如: 1-10):'
                        }
                    ]);

                    const rangeParts = walletRange.split('-');
                    if (rangeParts.length !== 2) {
                        console.log('\n无效的范围格式!请使用 "起始-结束" 格式,例如: 1-10');
                        continue;
                    }

                    const toStart = parseInt(rangeParts[0].trim());
                    const toEnd = parseInt(rangeParts[1].trim());

                    if (isNaN(toStart) || isNaN(toEnd) || toStart < 1 || toEnd < toStart) {
                        console.log('\n无效的接收方钱包编号范围!');
                        continue;
                    }

                    const receiverCount = toEnd - toStart + 1;
                    console.log(`\n接收方钱包范围: ${toStart} 到 ${toEnd},共 ${receiverCount} 个钱包`);

                    const { minAmount } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'minAmount',
                            message: '请输入最小转账金额 (SOL):'
                        }
                    ]);

                    const { maxAmount } = await inquirer.prompt([
                        {
                            type: 'input',
                            name: 'maxAmount',
                            message: '请输入最大转账金额 (SOL):'
                        }
                    ]);

                    const minAmountFloat = parseFloat(minAmount);
                    const maxAmountFloat = parseFloat(maxAmount);

                    if (isNaN(minAmountFloat) || isNaN(maxAmountFloat) || minAmountFloat <= 0 || maxAmountFloat <= 0) {
                        console.log('\n请输入有效的正数金额!');
                        continue;
                    }

                    if (minAmountFloat >= maxAmountFloat) {
                        console.log('\n最小金额必须小于最大金额!');
                        continue;
                    }

                    // 生成随机金额数组进行预估
                    let totalEstimatedAmount = 0;
                    const estimatedAmounts = [];

                    for (let i = 0; i < receiverCount; i++) {
                        const randomAmount = parseFloat((Math.random() * (maxAmountFloat - minAmountFloat) + minAmountFloat).toFixed(6));
                        estimatedAmounts.push(randomAmount);
                        totalEstimatedAmount += randomAmount;
                    }

                    // 计算估计的交易费用
                    const estimatedFees = this.feeReserve * receiverCount;
                    const totalRequired = totalEstimatedAmount + estimatedFees;

                    console.log(`\n随机金额范围: ${minAmountFloat} SOL 到 ${maxAmountFloat} SOL`);
                    console.log(`预计平均每笔转账: ${((minAmountFloat + maxAmountFloat) / 2).toFixed(6)} SOL`);
                    console.log(`预计总转账金额: ${totalEstimatedAmount.toFixed(6)} SOL`);
                    console.log(`估计交易费用: ${estimatedFees.toFixed(6)} SOL`);
                    console.log(`总计需要: ${totalRequired.toFixed(6)} SOL`);

                    // 再次检查发送方余额是否足够
                    try {
                        const { address: fromAddress } = await this.getWalletFromNumber(fromFolderNum.trim(), parseInt(fromWalletIndex));
                        const balance = await this.getBalance(fromAddress);

                        if (balance < totalRequired) {
                            console.log(`\n错误: 发送方钱包余额不足!`);
                            console.log(`需要: ${totalRequired.toFixed(6)} SOL`);
                            console.log(`当前余额: ${balance} SOL`);
                            console.log(`差额: ${(totalRequired - balance).toFixed(6)} SOL`);
                            continue;
                        }

                        console.log(`\n发送方余额充足,可以继续转账操作。`);
                        console.log(`当前余额: ${balance} SOL`);
                        console.log(`转账后预计剩余: ${(balance - totalRequired).toFixed(6)} SOL`);
                    } catch (error) {
                        console.error(`\n错误: 检查发送方钱包余额失败: ${error.message}`);
                        continue;
                    }

                    // 确认是否继续
                    const { confirmTransfer } = await inquirer.prompt([
                        {
                            type: 'confirm',
                            name: 'confirmTransfer',
                            message: '确认要执行以上转账操作吗?',
                            default: false
                        }
                    ]);

                    if (!confirmTransfer) {
                        console.log('\n已取消转账操作。');
                        continue;
                    }

                    const { password } = await inquirer.prompt([
                        {
                            type: 'password',
                            name: 'password',
                            message: '请输入钱包密码:',
                            mask: '*'
                        }
                    ]);

                    try {
                        const results = await this.oneToManyRandomTransfer(
                            fromFolderNum.trim(),
                            parseInt(fromWalletIndex),
                            toFolderNum.trim(),
                            toStart,
                            toEnd,
                            minAmountFloat,
                            maxAmountFloat,
                            password
                        );
                        this.displayTransferResults(results);
                    } catch (error) {
                        console.error(`\n错误: ${error.message}`);
                    }
                } else if (action === '5') {
                    console.log('\n再见!');
                    break;
                }
            }
        } catch (error) {
            console.error(`发生错误: ${error.message}`);
        }
    }

    displayTransferResults(results) {
        console.log('\n=== 转账结果摘要 ===');
        const successCount = results.filter(r => r.success).length;
        const failCount = results.length - successCount;

        console.log(`总计: ${results.length} 笔交易`);
        console.log(`成功: ${successCount} 笔`);
        console.log(`失败: ${failCount} 笔`);

        if (failCount > 0) {
            console.log('\n失败的交易:');
            results.filter(r => !r.success).forEach(r => {
                console.log(`- 钱包 #${r.pair}: 从 ${r.from} 到 ${r.to}, ${r.amount} SOL`);
                console.log(`  错误: ${r.error}`);
            });
        }
    }

    async loadWallet(walletPath, password) {
        try {
            // 检查钱包文件是否存在
            if (!fs.existsSync(walletPath)) {
                throw new Error(`钱包文件不存在: ${walletPath}`);
            }

            // 读取钱包文件
            let walletData;
            try {
                walletData = fs.readJsonSync(walletPath);
            } catch (readError) {
                throw new Error(`读取钱包文件失败: ${readError.message}`);
            }

            // 检查钱包文件格式
            if (!walletData.encryptedPrivateKey) {
                throw new Error(`钱包文件格式错误: 缺少加密私钥`);
            }

            // 使用与SolanaAddressGenerator完全相同的解密方法
            let privateKey;
            try {
                // 使用相同的方法从密码生成密钥
                const key = CryptoJS.PBKDF2(password, 'salt', {
                    keySize: 256 / 32,
                    iterations: 100000
                });

                // 使用密钥解密
                const decrypted = CryptoJS.AES.decrypt(walletData.encryptedPrivateKey, key.toString());
                privateKey = decrypted.toString(CryptoJS.enc.Utf8);

                if (!privateKey) {
                    throw new Error('密码错误或私钥格式损坏');
                }
            } catch (decryptError) {
                throw new Error(`解密私钥失败: ${decryptError.message}`);
            }

            // 创建 Keypair
            try {
                // 解码 base58 格式的私钥
                const secretKey = bs58.decode(privateKey);
                const keypair = Keypair.fromSecretKey(secretKey);

                // 验证公钥是否与钱包文件中的地址匹配
                if (walletData.address && keypair.publicKey.toString() !== walletData.address) {
                    throw new Error('解密的私钥与钱包地址不匹配');
                }

                return keypair;
            } catch (keypairError) {
                throw new Error(`创建密钥对失败: ${keypairError.message}`);
            }
        } catch (error) {
            console.error(`加载钱包失败: ${error.message}`);
            throw new Error(`加载钱包失败: ${error.message}`);
        }
    }

    getBalance(address) {
        try {
            console.log(`正在查询地址 ${address} 的余额...`);
            return this.balanceChecker.checkBalance(address);
        } catch (error) {
            console.error(`查询余额失败: ${error.message}`);
            throw new Error(`查询余额失败: ${error.message}`);
        }
    }

    async getMinimumRentExemption() {
        if (this.minRentExemption === null) {
            try {
                // 获取最小账户大小的租金豁免金额
                const rentExemptionInLamports = await this.connection.getMinimumBalanceForRentExemption(0);
                // 转换为 SOL 并缓存
                this.minRentExemption = rentExemptionInLamports / 1e9;
            } catch (error) {
                console.error(`获取最小租金豁免金额失败: ${error.message}`);
                // 使用默认值
                this.minRentExemption = 0.00089088;
            }
        }
        return this.minRentExemption;
    }

    async transferSol(fromPrivateKey, toAddress, amount) {
        try {
            // 创建发送方密钥对
            let fromKeypair;
            try {
                // 如果传入的是字符串格式的私钥,转换为Keypair对象
                if (typeof fromPrivateKey === 'string') {
                    const secretKey = bs58.decode(fromPrivateKey);
                    fromKeypair = Keypair.fromSecretKey(secretKey);
                } else if (fromPrivateKey instanceof Keypair) {
                    // 如果已经是Keypair对象,直接使用
                    fromKeypair = fromPrivateKey;
                } else {
                    throw new Error('无效的私钥格式');
                }
            } catch (keypairError) {
                throw new Error(`创建发送方密钥对失败: ${keypairError.message}`);
            }

            // 创建接收方公钥
            let toPublicKey;
            try {
                toPublicKey = new PublicKey(toAddress);
            } catch (pubkeyError) {
                throw new Error(`无效的接收方地址: ${pubkeyError.message}`);
            }

            // 检查发送方余额是否足够
            const fromAddress = fromKeypair.publicKey.toString();
            const balance = await this.getBalance(fromAddress);

            if (balance < amount + this.feeReserve) {
                throw new Error(`余额不足以完成交易,需要 ${amount + this.feeReserve} SOL (包含估计费用),但只有 ${balance} SOL`);
            }

            // 创建转账指令
            const lamports = Math.round(amount * LAMPORTS_PER_SOL);
            const transferInstruction = SystemProgram.transfer({
                fromPubkey: fromKeypair.publicKey,
                toPubkey: toPublicKey,
                lamports: lamports
            });

            // 创建交易
            const transaction = new Transaction().add(transferInstruction);

            // 获取最新的区块哈希
            const { blockhash, lastValidBlockHeight } = await this.connection.getLatestBlockhash();
            transaction.recentBlockhash = blockhash;
            transaction.feePayer = fromKeypair.publicKey;

            // 签名交易
            try {
                transaction.sign(fromKeypair);
            } catch (signError) {
                throw new Error(`交易签名失败: ${signError.message}`);
            }

            // 发送交易
            try {
                const signature = await this.connection.sendRawTransaction(
                    transaction.serialize()
                );

                // 不等待交易确认,直接返回交易哈希
                console.log(`交易已发送,哈希: ${signature}`);
                console.log(`注意: 不等待链上确认,交易可能仍在处理中`);

                return {
                    txId: signature,
                    signature: signature
                };
            } catch (sendError) {
                // 提取更详细的错误信息
                let errorMessage = sendError.message;
                if (sendError.logs) {
                    errorMessage += `\n日志: ${JSON.stringify(sendError.logs, null, 2)}`;
                }
                throw new Error(`发送交易失败: ${errorMessage}`);
            }
        } catch (error) {
            console.error(`转账SOL失败: ${error.message}`);
            throw new Error(`转账SOL失败: ${error.message}`);
        }
    }

    // 计算安全转账金额(考虑交易费用)
    calculateSafeTransferAmount(balance, isTransferAll = false) {
        if (isTransferAll && balance > this.feeReserve) {
            return balance - this.feeReserve;
        }

        return balance;
    }

    // 获取钱包信息
    async getWalletFromNumber(folderNum, walletIndex) {
        try {
            // 创建主钱包目录
            const mainWalletDir = path.join(process.cwd(), 'wallets');
            if (!fs.existsSync(mainWalletDir)) {
                fs.mkdirSync(mainWalletDir, { recursive: true });
            }

            // 构建文件夹路径
            const folderName = `wallets${folderNum}`;
            const folderPath = path.join(mainWalletDir, folderName);

            if (!fs.existsSync(folderPath)) {
                throw new Error(`找不到文件夹 ${folderName}`);
            }

            // 获取文件夹中的所有钱包文件
            const walletFiles = fs.readdirSync(folderPath)
                .filter(file => file.endsWith('.json'))
                .sort();

            if (walletFiles.length === 0) {
                throw new Error(`${folderName} 中没有钱包文件`);
            }

            if (walletIndex < 1 || walletIndex > walletFiles.length) {
                throw new Error(`无效的钱包编号,应为 1 到 ${walletFiles.length}`);
            }

            // 获取指定的钱包文件
            const walletFile = walletFiles[walletIndex - 1];
            const walletPath = path.join(folderPath, walletFile);

            // 读取钱包地址
            const data = fs.readJsonSync(walletPath);
            const address = data.address;

            return { walletPath, address };
        } catch (error) {
            throw new Error(`获取钱包信息失败: ${error.message}`);
        }
    }

    async getWalletsInFolder(folderNum) {
        try {
            // 创建主钱包目录
            const mainWalletDir = path.join(process.cwd(), 'wallets');
            if (!fs.existsSync(mainWalletDir)) {
                fs.mkdirSync(mainWalletDir, { recursive: true });
            }

            // 构建文件夹路径
            const folderName = `wallets${folderNum}`;
            const folderPath = path.join(mainWalletDir, folderName);

            if (!fs.existsSync(folderPath)) {
                throw new Error(`找不到文件夹 ${folderName}`);
            }

            // 获取文件夹中的所有钱包文件
            const walletFiles = fs.readdirSync(folderPath)
                .filter(file => file.endsWith('.json'))
                .sort();

            if (walletFiles.length === 0) {
                throw new Error(`${folderName} 中没有钱包文件`);
            }

            // 读取每个钱包文件的信息
            const wallets = [];
            for (let i = 0; i < walletFiles.length; i++) {
                try {
                    const walletFile = walletFiles[i];
                    const walletPath = path.join(folderPath, walletFile);

                    // 读取钱包地址
                    const data = fs.readJsonSync(walletPath);
                    const address = data.address;

                    wallets.push({
                        index: i + 1,
                        file: walletFile,
                        path: walletPath,
                        address
                    });
                } catch (error) {
                    console.error(`读取钱包 ${walletFiles[i]} 失败: ${error.message}`);
                }
            }

            return wallets;
        } catch (error) {
            throw new Error(`获取文件夹钱包列表失败: ${error.message}`);
        }
    }

    // 文件夹间转账(多转多)
    async folderToFolderTransfer(fromFolderNum, toFolderNum, password) {
        try {
            // 获取两个文件夹中的钱包列表
            const fromWallets = await this.getWalletsInFolder(fromFolderNum);
            const toWallets = await this.getWalletsInFolder(toFolderNum);

            // 检查两个文件夹中的钱包数量是否相同
            if (fromWallets.length !== toWallets.length) {
                throw new Error(`两个文件夹中的钱包数量不同: 发送方有 ${fromWallets.length} 个钱包,接收方有 ${toWallets.length} 个钱包`);
            }

            // 获取最小租金豁免金额
            const minRentExemption = await this.getMinimumRentExemption();

            // 执行转账
            const results = [];
            for (let i = 0; i < fromWallets.length; i++) {
                const fromWallet = fromWallets[i];
                const toWallet = toWallets[i];

                try {
                    // 检查发送方余额
                    const balance = await this.getBalance(fromWallet.address);
                    if (balance <= 0) {
                        // 忽略余额为0的钱包,不添加到结果中
                        console.log(`\n跳过钱包 #${fromWallet.index}: 余额为零`);
                        continue;
                    }

                    // 检查接收方账户是否存在
                    const receiverExists = await this.isAccountExists(toWallet.address);
                    if (!receiverExists && balance < minRentExemption) {
                        results.push({
                            pair: fromWallet.index,
                            from: fromWallet.address,
                            to: toWallet.address,
                            amount: balance,
                            error: `接收方账户未激活,转账金额不足以支付租金 (最小 ${minRentExemption} SOL)`,
                            success: false
                        });
                        continue;
                    }

                    // 加载发送方钱包
                    const fromKeypair = await this.loadWallet(fromWallet.path, password);
                    const fromPrivateKey = bs58.encode(fromKeypair.secretKey);

                    // 预留交易费用
                    const transferAmount = balance - this.transferFee;

                    if (transferAmount <= 0) {
                        console.log(`\n跳过钱包 #${fromWallet.index}: 余额不足以支付交易费用`);
                        continue;
                    }

                    // 执行转账
                    console.log(`\n转账对 #${fromWallet.index}:`);
                    console.log(`从: ${fromWallet.address}`);
                    console.log(`到: ${toWallet.address}`);
                    console.log(`金额: ${transferAmount} SOL (预留 ${this.feeReserve} SOL 作为交易费用)`);

                    const txHash = await this.transferSol(fromPrivateKey, toWallet.address, transferAmount);

                    results.push({
                        pair: fromWallet.index,
                        from: fromWallet.address,
                        to: toWallet.address,
                        amount: transferAmount,
                        txHash: txHash.txId,
                        success: true
                    });
                } catch (error) {
                    results.push({
                        pair: fromWallet.index,
                        from: fromWallet.address,
                        to: toWallet.address,
                        amount: 0,
                        error: error.message,
                        success: false
                    });
                }
            }

            return results;
        } catch (error) {
            throw new Error(`文件夹间转账失败: ${error.message}`);
        }
    }

    // 一对多固定金额转账
    async oneToManyTransferWithAmounts(fromFolderNum, fromWalletIndex, toFolderNum, toStart, toEnd, amounts, password) {
        try {
            // 获取发送方钱包信息
            const { walletPath: fromWalletPath, address: fromAddress } = await this.getWalletFromNumber(fromFolderNum, fromWalletIndex);

            // 先验证密码是否正确
            console.log(`\n正在验证钱包密码...`);
            const verifyResult = await this.verifyWalletPassword(fromWalletPath, password);
            if (!verifyResult.success) {
                throw new Error(`密码验证失败: ${verifyResult.message}`);
            }
            console.log(`密码验证成功,继续转账操作。`);

            // 加载发送方钱包
            console.log(`调试信息: 加载发送方钱包...`);
            const fromKeypair = await this.loadWallet(fromWalletPath, password);
            console.log(`调试信息: 成功加载发送方钱包,公钥: ${fromKeypair.publicKey.toString()}`);

            // 检查发送方余额
            const balance = await this.getBalance(fromAddress);

            // 计算总转账金额
            const totalAmount = amounts.reduce((sum, a) => sum + a, 0);

            // 检查余额是否足够
            if (balance < totalAmount) {
                throw new Error(`发送方余额不足,需要 ${totalAmount} SOL,但只有 ${balance} SOL`);
            }

            // 获取最小租金豁免金额
            const minRentExemption = await this.getMinimumRentExemption();

            // 检查每个接收方账户
            const results = [];

            for (let i = toStart; i <= toEnd; i++) {
                try {
                    // 获取接收方钱包信息
                    const { walletPath: toWalletPath, address: toAddress } = await this.getWalletFromNumber(toFolderNum, i);

                    console.log(`\n转账对 #${i}:`);
                    console.log(`从: ${fromAddress}`);
                    console.log(`到: ${toAddress} (钱包 #${i})`);
                    console.log(`金额: ${amounts[i - toStart]} SOL`);

                    // 检查接收方账户是否存在
                    const receiverExists = await this.isAccountExists(toAddress);

                    // 如果接收方账户不存在,检查转账金额是否足够支付租金
                    if (!receiverExists && amounts[i - toStart] < minRentExemption) {
                        console.log(`警告: 接收方钱包 #${i} (${toAddress}) 未激活,转账金额 ${amounts[i - toStart]} SOL 不足以支付租金 (最小 ${minRentExemption} SOL)`);

                        results.push({
                            pair: i,
                            from: fromAddress,
                            to: toAddress,
                            amount: amounts[i - toStart],
                            error: `接收方账户未激活,转账金额不足以支付租金 (最小 ${minRentExemption} SOL)`,
                            success: false
                        });
                        continue;
                    }

                    // 执行转账 - 直接使用Keypair对象
                    const txHash = await this.transferSol(fromKeypair, toAddress, amounts[i - toStart]);
                    console.log(`交易成功: ${txHash}`);

                    results.push({
                        pair: i,
                        from: fromAddress,
                        to: toAddress,
                        amount: amounts[i - toStart],
                        txHash,
                        success: true
                    });
                } catch (error) {
                    try {
                        const { address: toAddress } = await this.getWalletFromNumber(toFolderNum, i);

                        results.push({
                            pair: i,
                            from: fromAddress,
                            to: toAddress,
                            amount: amounts[i - toStart],
                            error: error.message,
                            success: false
                        });
                    } catch (e) {
                        results.push({
                            pair: i,
                            from: fromAddress,
                            to: '获取地址失败',
                            amount: amounts[i - toStart],
                            error: error.message,
                            success: false
                        });
                    }
                    console.error(`转账失败: ${error.message}`);
                }
            }

            return results;
        } catch (error) {
            throw new Error(`一对多转账失败: ${error.message}`);
        }
    }

    // 钱包间转账
    async transferBetweenWallets(fromFolderNum, fromWalletIndex, toFolderNum, toWalletIndex, amount, password) {
        try {
            // 加载发送方钱包
            let fromWallet;
            try {
                fromWallet = await this.localWallets.getWalletFromNumber(fromFolderNum, fromWalletIndex, password);
            } catch (error) {
                if (error.message.includes('密码错误') || error.message.includes('password')) {
                    throw new Error('密码错误,请重新输入');
                } else if (error.message.includes('不存在')) {
                    throw new Error(`发送方钱包文件夹 ${fromFolderNum} 或钱包编号 ${fromWalletIndex} 不存在`);
                } else {
                    throw new Error(`加载发送方钱包失败: ${error.message}`);
                }
            }

            // 加载接收方钱包
            let toWalletAddress;
            try {
                const { address } = await this.localWallets.getWalletAddressFromNumber(toFolderNum, toWalletIndex);
                toWalletAddress = address;
                console.log(`接收方钱包地址: ${toWalletAddress}`);
            } catch (error) {
                if (error.message.includes('不存在')) {
                    throw new Error(`接收方钱包文件夹 ${toFolderNum} 或钱包编号 ${toWalletIndex} 不存在`);
                } else {
                    throw new Error(`加载接收方钱包失败: ${error.message}`);
                }
            }

            // 执行转账
            const result = await this.transferSol(
                fromWallet,
                toWalletAddress,
                amount
            );

            return {
                txId: result.txId,
                signature: result.signature,
                fromAddress: fromWallet.publicKey.toString(),
                toAddress: toWalletAddress
            };
        } catch (error) {
            console.error('钱包间转账失败:', error);
            throw error;
        }
    }

    // 创建交易
    async createTransaction(fromPrivateKey, instructions) {
        try {
            const recentBlockhash = await this.connection.getLatestBlockhash();
            const transaction = new Transaction({
                feePayer: fromPrivateKey.publicKey,
                ...recentBlockhash,
            });

            // 添加所有指令
            transaction.add(...instructions);

            // 签名交易
            transaction.sign(fromPrivateKey);

            return transaction;
        } catch (error) {
            throw new Error(`创建交易失败: ${error.message}`);
        }
    }

    // 发送交易
    async sendTransaction(transaction) {
        try {
            // 发送交易
            const signature = await this.connection.sendRawTransaction(
                transaction.serialize()
            );

            // 不等待交易确认,直接返回交易哈希
            console.log(`交易已发送,哈希: ${signature}`);
            console.log(`注意: 不等待链上确认,交易可能仍在处理中`);

            return signature;
        } catch (error) {
            throw new Error(`发送交易失败: ${error.message}`);
        }
    }

    // 检查账户是否存在
    async isAccountExists(address) {
        try {
            const pubkey = new PublicKey(address);
            const accountInfo = await this.connection.getAccountInfo(pubkey);
            return accountInfo !== null;
        } catch (error) {
            console.error(`检查账户存在失败: ${error.message}`);
            return false;
        }
    }

    // 验证钱包密码
    async verifyWalletPassword(walletPath, password) {
        try {
            // 检查钱包文件是否存在
            if (!fs.existsSync(walletPath)) {
                return { success: false, message: `钱包文件不存在: ${walletPath}` };
            }

            // 读取钱包文件
            let walletData;
            try {
                walletData = fs.readJsonSync(walletPath);
            } catch (readError) {
                return { success: false, message: `读取钱包文件失败: ${readError.message}` };
            }

            // 检查钱包文件格式
            if (!walletData.encryptedPrivateKey) {
                return { success: false, message: `钱包文件格式错误: 缺少加密私钥` };
            }

            // 使用与SolanaAddressGenerator完全相同的解密方法
            let privateKey;
            try {
                // 使用相同的方法从密码生成密钥
                const key = CryptoJS.PBKDF2(password, 'salt', {
                    keySize: 256 / 32,
                    iterations: 100000
                });

                // 使用密钥解密
                const decrypted = CryptoJS.AES.decrypt(walletData.encryptedPrivateKey, key.toString());
                privateKey = decrypted.toString(CryptoJS.enc.Utf8);

                if (!privateKey) {
                    return { success: false, message: '密码错误' };
                }
            } catch (decryptError) {
                return { success: false, message: `解密私钥失败: ${decryptError.message}` };
            }

            // 验证解密后的私钥
            try {
                // 解码 base58 格式的私钥
                const secretKey = bs58.decode(privateKey);
                const keypair = Keypair.fromSecretKey(secretKey);

                // 验证公钥是否与钱包文件中的地址匹配
                if (walletData.address && keypair.publicKey.toString() !== walletData.address) {
                    return { success: false, message: '解密的私钥与钱包地址不匹配' };
                }

                return { success: true, message: '密码验证成功' };
            } catch (keypairError) {
                return { success: false, message: `私钥无效: ${keypairError.message}` };
            }
        } catch (error) {
            return { success: false, message: `验证密码失败: ${error.message}` };
        }
    }

    // 一对多随机金额转账
    async oneToManyRandomTransfer(fromFolderNum, fromWalletIndex, toFolderNum, toStart, toEnd, minAmount, maxAmount, password) {
        try {
            // 获取发送方钱包信息
            const { walletPath: fromWalletPath, address: fromAddress } = await this.getWalletFromNumber(fromFolderNum, fromWalletIndex);

            // 先验证密码是否正确
            console.log(`\n正在验证钱包密码...`);
            const verifyResult = await this.verifyWalletPassword(fromWalletPath, password);
            if (!verifyResult.success) {
                throw new Error(`密码验证失败: ${verifyResult.message}`);
            }
            console.log(`密码验证成功,继续转账操作。`);

            // 检查发送方余额
            let balance;
            try {
                console.log(`正在查询发送方钱包 ${fromAddress} 的余额...`);
                balance = await this.getBalance(fromAddress);
                console.log(`发送方钱包余额: ${balance} SOL`);
            } catch (error) {
                console.error(`查询发送方余额失败: ${error.message}`);
                throw new Error(`查询发送方余额失败: ${error.message}`);
            }

            // 计算接收方数量
            const receiverCount = toEnd - toStart + 1;

            if (receiverCount <= 0) {
                throw new Error('接收方钱包范围无效');
            }

            // 生成随机金额
            const amounts = [];
            let totalAmount = 0;

            for (let i = 0; i < receiverCount; i++) {
                // 生成minAmount到maxAmount之间的随机数
                const randomAmount = minAmount + Math.random() * (maxAmount - minAmount);
                // 保留6位小数
                const roundedAmount = Math.round(randomAmount * 1000000) / 1000000;
                amounts.push(roundedAmount);
                totalAmount += roundedAmount;
            }

            console.log(`接收方钱包数量: ${receiverCount}`);
            console.log(`随机金额范围: ${minAmount} - ${maxAmount} SOL`);
            console.log(`总转账金额: ${totalAmount.toFixed(6)} SOL`);

            // 检查余额是否足够
            if (balance < totalAmount) {
                throw new Error(`发送方余额不足,需要 ${totalAmount.toFixed(6)} SOL,但只有 ${balance} SOL`);
            }

            // 加载发送方钱包
            console.log(`调试信息: 加载发送方钱包...`);
            const fromKeypair = await this.loadWallet(fromWalletPath, password);
            console.log(`调试信息: 成功加载发送方钱包,公钥: ${fromKeypair.publicKey.toString()}`);

            // 获取最小租金豁免金额
            const minRentExemption = await this.getMinimumRentExemption();

            // 获取所有接收方钱包信息
            console.log(`正在获取所有接收方钱包信息...`);
            const receiverWallets = [];
            const receiverAddresses = [];

            for (let i = toStart; i <= toEnd; i++) {
                try {
                    const wallet = await this.getWalletFromNumber(toFolderNum, i);
                    receiverWallets.push({
                        index: i,
                        ...wallet
                    });
                    receiverAddresses.push(wallet.address);
                } catch (error) {
                    console.error(`获取接收方钱包 #${i} 信息失败: ${error.message}`);
                    // 添加失败记录
                    receiverWallets.push({
                        index: i,
                        error: error.message
                    });
                }
            }

            // 批量检查接收方账户是否存在
            console.log(`正在批量检查 ${receiverAddresses.length} 个接收方账户...`);
            let accountExistsMap = {};

            try {
                // 使用批量查询获取所有接收方账户的余额
                const balances = await this.balanceChecker.checkMultipleBalances(receiverAddresses);

                // 如果余额大于0,账户肯定存在
                // 如果余额为0,我们需要进一步检查账户是否存在
                for (const address of receiverAddresses) {
                    accountExistsMap[address] = balances[address] > 0;
                }

                // 对于余额为0的账户,我们需要进一步检查
                const zeroBalanceAddresses = receiverAddresses.filter(addr => balances[addr] === 0);
                if (zeroBalanceAddresses.length > 0) {
                    console.log(`有 ${zeroBalanceAddresses.length} 个账户余额为0,进一步检查账户是否存在...`);

                    // 将地址转换为PublicKey对象
                    const publicKeys = zeroBalanceAddresses.map(addr => new PublicKey(addr));

                    // 批量获取账户信息
                    const accountInfos = await this.connection.getMultipleAccountsInfo(publicKeys);

                    // 更新账户存在状态
                    zeroBalanceAddresses.forEach((addr, index) => {
                        accountExistsMap[addr] = accountInfos[index] !== null;
                    });
                }
            } catch (error) {
                console.error(`批量检查接收方账户失败: ${error.message}`);
                console.log(`将回退到单个检查每个账户...`);

                // 如果批量检查失败,回退到单个检查
                for (const address of receiverAddresses) {
                    try {
                        accountExistsMap[address] = await this.isAccountExists(address);
                    } catch (err) {
                        console.error(`检查账户 ${address} 失败: ${err.message}`);
                        accountExistsMap[address] = false;
                    }
                }
            }

            // 执行转账
            const results = [];
            let successCount = 0;
            let failCount = 0;
            let totalTransferred = 0;

            for (let j = 0; j < receiverWallets.length; j++) {
                const receiverWallet = receiverWallets[j];
                const amount = amounts[j];

                // 如果获取钱包信息失败,添加失败记录
                if (receiverWallet.error) {
                    results.push({
                        pair: receiverWallet.index,
                        from: fromAddress,
                        to: '获取地址失败',
                        amount: amount,
                        error: receiverWallet.error,
                        success: false
                    });
                    failCount++;
                    continue;
                }

                const toAddress = receiverWallet.address;
                const i = receiverWallet.index;

                try {
                    console.log(`\n转账对 #${i}:`);
                    console.log(`从: ${fromAddress}`);
                    console.log(`到: ${toAddress} (钱包 #${i})`);
                    console.log(`金额: ${amount} SOL`);

                    // 检查接收方账户是否存在
                    const receiverExists = accountExistsMap[toAddress];

                    // 如果接收方账户不存在,检查转账金额是否足够支付租金
                    if (!receiverExists && amount < minRentExemption) {
                        console.log(`警告: 接收方钱包 #${i} (${toAddress}) 未激活,转账金额 ${amount} SOL 不足以支付租金 (最小 ${minRentExemption} SOL)`);

                        results.push({
                            pair: i,
                            from: fromAddress,
                            to: toAddress,
                            amount: amount,
                            error: `接收方账户未激活,转账金额不足以支付租金 (最小 ${minRentExemption} SOL)`,
                            success: false
                        });
                        failCount++;
                        continue;
                    }

                    // 执行转账 - 直接使用Keypair对象
                    const txHash = await this.transferSol(fromKeypair, toAddress, amount);
                    console.log(`交易成功: ${txHash}`);

                    results.push({
                        pair: i,
                        from: fromAddress,
                        to: toAddress,
                        amount: amount,
                        txHash,
                        success: true
                    });
                    successCount++;
                    totalTransferred += amount;
                } catch (error) {
                    console.error(`转账失败: ${error.message}`);
                    results.push({
                        pair: i,
                        from: fromAddress,
                        to: toAddress,
                        amount: amount,
                        error: error.message,
                        success: false
                    });
                    failCount++;
                }
            }

            // 显示转账结果摘要
            console.log(`\n转账操作完成:`);
            console.log(`成功: ${successCount}/${receiverCount} 笔`);
            console.log(`失败: ${failCount}/${receiverCount} 笔`);
            console.log(`实际转账总金额: ${totalTransferred.toFixed(6)} SOL`);

            return results;
        } catch (error) {
            throw new Error(`一对多随机金额转账失败: ${error.message}`);
        }
    }
}

if (require.main === module) {
    const transfer = new SolanaTransfer();
    transfer.run();
}

// 导出SolanaTransfer类
module.exports = SolanaTransfer;
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
stephenCheung
stephenCheung
0x0b2D...9feb
java,go,solidity,rust智能合约开发者,专注defi领域研究