https://solscan.io/tx/5CpvpQuG8pU3x6xz3fmryqwtQkstnk4jQTP95ZgzPBAzhZipEGnpD8YnHxASsHkChotvihSxrjboret3YYD82u6z

https://solscan.io/tx/4Axs7CTRZNPeSWVqtYaP96KdB7hNafHq9AfUJenqVdP2oeZ1P9ggTfUu7zytvgDw1fGULGXYUqSwkNfEgsXMncPM

https://solscan.io/tx/TjN1kWn8MabXisVeKq37DXDDMaGKaLKSoztXUSxV8SfMzyfpi2T1rRGQeX3dAH41ygTuGb4zTfRKocpNq6FZaXH

import os
import time
import base58  
from solders.pubkey import Pubkey
from solders.keypair import Keypair
from solders.transaction import Transaction
from solders.message import Message  
from solders.compute_budget import set_compute_unit_price
from solana.rpc.api import Client
from solana.rpc.types import TxOpts
from solana.rpc.commitment import Confirmed
from spl.token.client import Token
from spl.token.constants import TOKEN_PROGRAM_ID
from spl.token.instructions import get_associated_token_address, create_associated_token_account, transfer_checked, TransferCheckedParams
from decimal import Decimal
# --- 1. 配置区域 ---
# --- 请在这里修改您的转账信息 ---

# 使用公共 RPC 节点
RPC_ENDPOINT = "<https://api.mainnet-beta.solana.com>"

# 要转账的代币的 Mint Address
TOKEN_MINT_ADDRESS = Pubkey.from_string("9raUVuzeWUk53co63M4WXLWPWE4Xc6Lpn7RS9dnkpump")
PRIVATE_KEY_STRING= "PRIVATE_KEY_STRING"
# 转账配置列表
TRANSFERS_CONFIG = [
    {"address": "8PnZWXHbJ7KDdVUnawABRPKwTxfmLiGRFPBTC87X7uqC", "amount": 0.11},
    {"address": "EBwyugmbUKMTUrtCq6aRTsyvfMGwJzp5yDRPrgNSqbHm", "amount": 0.12},
    {"address": "ENfD5o8xpfaANVTqwYf9DFQmHyC8ECnodvoxdNnZhZfJ", "amount": 0.13},
    {"address": "DEZA8LEEViuUD724gzPY8YdoM8PJ1woFssj4jrKENyqv", "amount": 0.14},
    {"address": "5iMiVc8hiEBub5RPjV7izouwyEJDPgFTnyT4tasNpdbL", "amount": 0.15},
    {"address": "Cm8GVbuayT55vnQhcnJmcKPaB5gvuPin67GnohordbHB", "amount": 0.16},
    {"address": "2GQTbSr7EtBor7QnD7gz7XpSkNF36pMXE9uAX9akFjKt", "amount": 0.17},
    {"address": "85M5nYP3ouHhdZjDdZh4W2HBn5DHB3kD1EHYiVNvNjyZ", "amount": 0.18},
    {"address": "GWJHAbXhgxdXoEWDHKBrzBB7pytbVzoipUQ4C8UNkniU", "amount": 0.19},
    {"address": "5w7psSQdRhEg6bhfjFQUs74ysB7KQdydKDhQcY3YpQXJ", "amount": 0.2},
    {"address": "5yogefKsED8oaBFcaSH92WSE8HvsrNwMUis7QZbG6aPZ", "amount": 0.21},
    {"address": "DEZA8LEEViuUD724gzPY8YdoM8PJ1woFssj4jrKENyqv", "amount": 0.22},
    {"address": "6yuUhK4MVh24nNnuYbSpviuoVFD4dZNqYdL7YPC7sFmU", "amount": 0.23},
    {"address": "ErdEeyoLaCkjnYZSG42JvbgRTrCLnFy7utw4ynbt9Fsq", "amount": 0.24},
    {"address": "DEZA8LEEViuUD724gzPY8YdoM8PJ1woFssj4jrKENyqv", "amount": 0.25},
    {"address": "5kek95xeUw2WeNbjgAsSJkUHnLbXgMgDuA5uU4o9K9M1", "amount": 0.26},
    {"address": "Z8wPQd3CZ6gYg9oHYsfKsZ6nyesSPCpwneXUW566y5U", "amount": 0.27},
    {"address": "G9HGnQJ1ahax2TCeczr5AZm27XPrkMUQ2f7EitAmALfs", "amount": 0.28},
    {"address": "DEZA8LEEViuUD724gzPY8YdoM8PJ1woFssj4jrKENyqv", "amount": 0.29},
]
# 优先费 (Micro Lamports)
PRIORITY_FEE_MICRO_LAMPORTS = 0
#单交易空投笔数
BATCH_SIZE = 9
# --- 配置区域结束 ---

def load_keypair_from_base58(private_key_b58: str) -> Keypair:
    try:
        keypair_bytes = base58.b58decode(private_key_b58)
        if len(keypair_bytes) != 64:
            raise ValueError(f"私钥解码后的长度应为64字节,实际为 {len(keypair_bytes)} 字节。")
        return Keypair.from_bytes(keypair_bytes)
    except Exception as e:
        print(f"错误:无法从Base58字符串加载密钥对。请检查.env文件中的私钥。")
        raise e

def main():
    """主执行函数"""
    print("--- Solana SPL 代币批量转账脚本 (兼容新版 solana-py) ---")

    # --- 新增:定义批量大小 ---
    # 根据计算,9 是一个在最坏情况下(所有接收者都需要创建ATA)也安全的值

    try:
        sender_keypair = load_keypair_from_base58(PRIVATE_KEY_STRING)
        client = Client(RPC_ENDPOINT)
    except Exception as e:
        print(f"初始化失败:{e}")
        return

    print(f"发送方地址: {sender_keypair.pubkey()}")
    print(f"代币地址: {TOKEN_MINT_ADDRESS}")
    print(f"共计 {len(TRANSFERS_CONFIG)} 笔转账任务,将以每批 {BATCH_SIZE} 笔进行处理")
    print("-" * 20)

    try:
        token_client = Token(
            conn=client,
            pubkey=TOKEN_MINT_ADDRESS,
            program_id=TOKEN_PROGRAM_ID,
            payer=sender_keypair
        )
        mint_info = token_client.get_mint_info()
        decimals = mint_info.decimals
        print(f"代币小数位数: {decimals}")

        sender_ata = get_associated_token_address(sender_keypair.pubkey(), TOKEN_MINT_ADDRESS)
        print(f"发送方代币账户 (ATA): {sender_ata}")

        # --- 核心改动:对转账任务进行分批处理 ---
        total_batches = (len(TRANSFERS_CONFIG) + BATCH_SIZE - 1) // BATCH_SIZE
        
        for i in range(0, len(TRANSFERS_CONFIG), BATCH_SIZE):
            batch_num = (i // BATCH_SIZE) + 1
            batch_config = TRANSFERS_CONFIG[i:i + BATCH_SIZE]
            
            print(f"\\n--- 正在处理批次 {batch_num}/{total_batches} (共 {len(batch_config)} 笔转账) ---")

            # 1. 将当前批次的指令收集到一个列表中
            instructions = []
            
            if PRIORITY_FEE_MICRO_LAMPORTS > 0:
                instructions.append(set_compute_unit_price(PRIORITY_FEE_MICRO_LAMPORTS))
                print(f"已添加优先费: {PRIORITY_FEE_MICRO_LAMPORTS} micro-lamports")

            print("正在为当前批次的每个接收者生成转账指令...")
            for transfer_info in batch_config:
                try:
                    recipient_pubkey = Pubkey.from_string(transfer_info["address"])
                    
                    # <--- 浮点精度修正
                    # 使用 Decimal 确保精度,先转为字符串再转 Decimal 是最安全的方式
                    amount_decimal = Decimal(str(transfer_info["amount"]))
                    amount_in_smallest_unit = int(amount_decimal * (10 ** decimals))
                    # ---> 浮点精度修正结束
                    
                    print(f"  -> 任务: 向 {recipient_pubkey} 转账 {amount_decimal} 个代币")

                    recipient_ata = get_associated_token_address(recipient_pubkey, TOKEN_MINT_ADDRESS)
                    recipient_ata_info = client.get_account_info(recipient_ata).value
                    if recipient_ata_info is None:
                        print(f"     接收者 ATA ({recipient_ata}) 不存在,将添加 '创建 ATA' 指令。")
                        instructions.append(
                            create_associated_token_account(
                                payer=sender_keypair.pubkey(),
                                owner=recipient_pubkey,
                                mint=TOKEN_MINT_ADDRESS
                            )
                        )
                    
                    instructions.append(
                        transfer_checked(
                            TransferCheckedParams(
                                program_id=token_client.program_id,
                                source=sender_ata,
                                mint=TOKEN_MINT_ADDRESS,
                                dest=recipient_ata,
                                owner=sender_keypair.pubkey(),
                                amount=amount_in_smallest_unit,
                                decimals=decimals,
                                signers=[]
                            )
                        )
                    )

                except Exception as e:
                    print(f"处理转账任务 {transfer_info} 时出错: {e}")
                    continue

            # 2. 获取最新区块哈希 (!!! 必须在每个批次循环内部获取)
            print("正在获取最新区块哈希...")
            latest_blockhash = client.get_latest_blockhash(commitment=Confirmed).value.blockhash

            # 3. 创建 Message 和 Transaction
            message = Message.new_with_blockhash(
                instructions,
                sender_keypair.pubkey(),
                latest_blockhash
            )
            transaction = Transaction([sender_keypair], message, latest_blockhash)
            
            # 4. 发送交易
            print("正在发送交易到 Solana 网络...")
            opts = TxOpts(skip_preflight=False, preflight_commitment=Confirmed)
            tx_signature = client.send_transaction(transaction, opts=opts).value
            
            print("-" * 20)
            print(f"✅ 批次 {batch_num} 交易已成功发送!")
            print(f"  交易签名: {tx_signature}")
            print(f"  在 Solscan 上查看: <https://solscan.io/tx/{tx_signature}>")
            
            print("正在等待交易确认...")
            client.confirm_transaction(tx_signature, commitment=Confirmed)
            print(f"🎉 批次 {batch_num} 交易已确认!")

            # 在批次之间短暂暂停,避免对 RPC 节点造成过大压力
            if batch_num < total_batches:
                time.sleep(2)

        print("\\n--- 所有批次处理完毕,批量转账完成 ---")

    except Exception as e:
        print(f"\\n❌ 执行过程中发生错误: {e}")

if __name__ == "__main__":
    main()