faucet_threading.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. # -*- coding: utf-8 -*-
  2. import time
  3. import random
  4. import threading
  5. from web3 import Web3
  6. from eth_account import Account
  7. private_key_list = [
  8. "2a185eae14ca82ac934a5f952e12e0d4a64043c911c33a19afd48ef1a1d70c46",
  9. "df5d009c711475b8f9987f235b373cfdbd93c858063efa9eebd9188dbc534097",
  10. "64f548051325022a7aa9e32c5756161d227fd5fb641c3f4623558cb574775254",
  11. "aa6fc003745793d7c192b2c404e332770b501ac0b81879d7538d6659ca84b7cf",
  12. "e92637de4029ae6397c18ff62cab0460e6caee1f166a0e710d52d46556c16627",
  13. "1741e24dd3a1a5cecf39dea82ba6ba62506d7a07ebcc7998b9b66eb8423e93db",
  14. "b898cf63a5ec89105ba755ef3b7533c25ea9130ab50fb0db14779fb6efd4f9c6",
  15. "f139f86b139f92070b6e6139177e59d85532c867dda6a8833e479fd60a8d37b7",
  16. "399ec8a9a9fcbb3118f993351c7624bdffc9b93d31e6576ebe69e9b24a2ecab3",
  17. "48cd0f0db84c9ca488292c9da449236d14a845e07618b6c0975cb158ccd60794"
  18. ]
  19. def claim_token(private_key):
  20. # 配置信息
  21. rpc_url = "https://rpc.sepolia.ethpandaops.io"
  22. target_chain_id = 11155111
  23. contract_address = "0x3edf60dd017ace33a0220f78741b5581c385a1ba"
  24. try:
  25. # 连接Web3
  26. web3 = Web3(Web3.HTTPProvider(rpc_url))
  27. if not web3.is_connected():
  28. print(f"❌ [{private_key[:8]}...] 无法连接到目标网络")
  29. return False
  30. # 校验链ID是否为Sepolia
  31. chain_id = web3.eth.chain_id
  32. if chain_id != target_chain_id:
  33. print(f"❌ [{private_key[:8]}...] 连接了错误的网络,当前链ID: {chain_id}, 期望: {target_chain_id}")
  34. return False
  35. # 创建账户对象
  36. account = Account.from_key("0x" + private_key)
  37. # 查询当前账户余额
  38. balance = web3.eth.get_balance(account.address)
  39. balance_eth = web3.from_wei(balance, 'ether')
  40. print(f"[{private_key[:8]}...] 当前账户余额: {balance_eth} Token")
  41. # 构造调用数据
  42. wallet_address = account.address[2:].lower() # 去掉0x前缀
  43. wallet_param = wallet_address.zfill(64) # 补足64位(32字节)
  44. call_data = "0x6a627842" + wallet_param
  45. # 构造交易
  46. transaction = {
  47. "to": Web3.to_checksum_address(contract_address),
  48. "value": 0,
  49. "gas": 100000, # 固定Gas限制,可根据需要调整
  50. "gasPrice": web3.to_wei(20, "gwei"), # 固定Gas价格,可调整
  51. "nonce": web3.eth.get_transaction_count(account.address),
  52. "data": call_data,
  53. "chainId": target_chain_id,
  54. }
  55. print(f"[{private_key[:8]}...] 📋 调用数据: {call_data}")
  56. print(f"[{private_key[:8]}...] 📤 发送交易中...")
  57. # 签名交易
  58. signed_txn = web3.eth.account.sign_transaction(transaction, private_key)
  59. # 发送交易
  60. tx_hash = web3.eth.send_raw_transaction(signed_txn.rawTransaction)
  61. tx_hash_hex = tx_hash.hex()
  62. print(f"[{private_key[:8]}...] 📤 交易已发送: {tx_hash_hex}")
  63. print(f"[{private_key[:8]}...] ⏳ 等待交易确认...")
  64. # 等待交易确认
  65. receipt = web3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)
  66. if receipt.status == 1:
  67. print(f"[{private_key[:8]}...] ✅ 代币领取成功! Gas使用: {receipt.gasUsed}")
  68. print(f"[{private_key[:8]}...] 🔗 交易链接: https://sepolia.etherscan.io/tx/{tx_hash_hex}")
  69. return True
  70. else:
  71. print(f"[{private_key[:8]}...] ❌ 交易执行失败")
  72. return False
  73. except Exception as e:
  74. error_msg = str(e).lower()
  75. if "insufficient funds" in error_msg:
  76. print(f"[{private_key[:8]}...] ❌ ETH余额不足,无法支付Gas费用")
  77. elif "nonce too low" in error_msg:
  78. print(f"[{private_key[:8]}...] ❌ Nonce值过低,请稍后重试")
  79. elif "replacement transaction underpriced" in error_msg:
  80. print(f"[{private_key[:8]}...] ❌ 交易费用过低,请提高Gas价格")
  81. else:
  82. print(f"[{private_key[:8]}...] ❌ 领取失败: {e}")
  83. return False
  84. def worker(private_key, claim_times):
  85. """为每个 private_key 执行的线程任务"""
  86. for i in range(claim_times):
  87. print(f"[{private_key[:8]}...] 开始领取第 {i+1} 次")
  88. n = 1
  89. retry_min_time = 10
  90. retry_max_time = 20
  91. retry_time = random.uniform(retry_min_time, retry_max_time)
  92. retry_max_times = 3
  93. while True:
  94. if n > retry_max_times:
  95. print(f"[{private_key[:8]}...] 领取 {i+1} 次失败, 重试次数超过 {retry_max_times} 次, 跳过")
  96. break
  97. if claim_token(private_key):
  98. break
  99. print(f"[{private_key[:8]}...] 领取 {i+1} 次失败, 重试第 {n} 次, 等待 {retry_time} 秒后再次领取")
  100. n += 1
  101. time.sleep(retry_time)
  102. print(f"[{private_key[:8]}...] 领取第 {i+1} 次成功, 等待 {retry_time} 秒后再次领取")
  103. time.sleep(retry_time)
  104. if __name__ == "__main__":
  105. claim_times = 20
  106. threads = []
  107. # 为每个 private_key 创建一个线程
  108. for private_key in private_key_list:
  109. thread = threading.Thread(target=worker, args=(private_key, claim_times))
  110. threads.append(thread)
  111. thread.start()
  112. # 等待所有线程完成
  113. for thread in threads:
  114. thread.join()
  115. print("所有线程已完成")