|
|
@@ -1,6 +1,7 @@
|
|
|
# -*- coding: utf-8 -*-
|
|
|
"""
|
|
|
Monad 测试网批量签到脚本(双合约版本)
|
|
|
+网址: of.apr.io
|
|
|
1. signIn() → 0x9E1DDC2a90bc0bec6325dF48Cbb3125Ce2879F7C 方法 0x9e4cda43
|
|
|
2. checkIn() → 0x703e753E9a2aCa1194DED65833EAec17dcFeAc1b 方法 0x183ff085
|
|
|
"""
|
|
|
@@ -8,51 +9,41 @@ Monad 测试网批量签到脚本(双合约版本)
|
|
|
import asyncio
|
|
|
import os
|
|
|
import random
|
|
|
-import time
|
|
|
from typing import List
|
|
|
|
|
|
from web3 import Web3
|
|
|
from web3.types import TxReceipt
|
|
|
+from eth_account import Account
|
|
|
|
|
|
# ------------------------ 用户配置区 ------------------------
|
|
|
RPC_URL = "https://testnet-rpc.monad.xyz"
|
|
|
|
|
|
-# 两个合约地址
|
|
|
SIGN_IN_CONTRACT = "0x9E1DDC2a90bc0bec6325dF48Cbb3125Ce2879F7C"
|
|
|
CHECK_IN_CONTRACT = "0x703e753E9a2aCa1194DED65833EAec17dcFeAc1b"
|
|
|
|
|
|
-# 私钥文件
|
|
|
KEY_FILE = "AccountList.txt"
|
|
|
-
|
|
|
-# 余额保护
|
|
|
MIN_KEEP_BALANCE = 0.02
|
|
|
-
|
|
|
-# 延时
|
|
|
MIN_DELAY = 15
|
|
|
MAX_DELAY = 30
|
|
|
+
|
|
|
# -----------------------------------------------------------
|
|
|
|
|
|
w3 = Web3(Web3.HTTPProvider(RPC_URL))
|
|
|
if not w3.is_connected():
|
|
|
raise RuntimeError("无法连接 RPC")
|
|
|
|
|
|
-# 方法选择器
|
|
|
SIGN_IN_SELECTOR = "0x9e4cda43"
|
|
|
CHECK_IN_SELECTOR = "0x183ff085"
|
|
|
|
|
|
-
|
|
|
-# ------------------------ 工具函数 ------------------------
|
|
|
def load_private_keys(path: str) -> List[str]:
|
|
|
if not os.path.isfile(path):
|
|
|
raise FileNotFoundError(f"找不到私钥文件: {path}")
|
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
|
return [line.strip() for line in f if line.strip()]
|
|
|
|
|
|
-
|
|
|
def random_gas_limit(base: int = 100_000) -> int:
|
|
|
return base + random.randint(-5_000, 10_000)
|
|
|
|
|
|
-
|
|
|
async def wait_tx(tx_hash: str) -> TxReceipt:
|
|
|
print(f"⏳ 等待交易确认: {tx_hash}")
|
|
|
receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=120)
|
|
|
@@ -62,13 +53,12 @@ async def wait_tx(tx_hash: str) -> TxReceipt:
|
|
|
print("❌ 失败")
|
|
|
return receipt
|
|
|
|
|
|
-
|
|
|
async def send_contract_call(private_key: str,
|
|
|
contract_addr: str,
|
|
|
selector: str,
|
|
|
desc: str):
|
|
|
- account = w3.eth.account.from_key(private_key)
|
|
|
- addr = account.address
|
|
|
+ acct = Account.from_key(private_key)
|
|
|
+ addr = acct.address
|
|
|
balance = w3.eth.get_balance(addr)
|
|
|
if w3.from_wei(balance, "ether") < MIN_KEEP_BALANCE:
|
|
|
print(f"⚠️ {addr} 余额不足,跳过")
|
|
|
@@ -85,37 +75,36 @@ async def send_contract_call(private_key: str,
|
|
|
"chainId": w3.eth.chain_id,
|
|
|
}
|
|
|
|
|
|
- signed = account.sign_transaction(tx)
|
|
|
- tx_hash = w3.eth.send_raw_transaction(signed.rawTransaction).hex() # <- 修正处
|
|
|
+ signed = Account.sign_transaction(tx, private_key)
|
|
|
+ # 注意新版为 raw_transaction,不是 rawTransaction
|
|
|
+ tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction).hex()
|
|
|
print(f"{desc} tx_hash: {tx_hash}")
|
|
|
await wait_tx(tx_hash)
|
|
|
|
|
|
-
|
|
|
async def process_account(private_key: str):
|
|
|
- account = w3.eth.account.from_key(private_key)
|
|
|
- print(f"\n========== 开始处理 {account.address} ==========")
|
|
|
+ acct = Account.from_key(private_key)
|
|
|
+ print(f"\n========== 开始处理 {acct.address} ==========")
|
|
|
|
|
|
try:
|
|
|
# 1. signIn
|
|
|
- await send_contract_call(
|
|
|
- private_key,
|
|
|
- SIGN_IN_CONTRACT,
|
|
|
- SIGN_IN_SELECTOR,
|
|
|
- "1️⃣ signIn"
|
|
|
- )
|
|
|
- await asyncio.sleep(random.uniform(MIN_DELAY, MAX_DELAY))
|
|
|
+ # await send_contract_call(
|
|
|
+ # private_key,
|
|
|
+ # SIGN_IN_CONTRACT,
|
|
|
+ # SIGN_IN_SELECTOR,
|
|
|
+ # "signIn"
|
|
|
+ # )
|
|
|
+ # await asyncio.sleep(random.uniform(MIN_DELAY, MAX_DELAY))
|
|
|
|
|
|
# 2. checkIn
|
|
|
await send_contract_call(
|
|
|
private_key,
|
|
|
CHECK_IN_CONTRACT,
|
|
|
CHECK_IN_SELECTOR,
|
|
|
- "2️⃣ checkIn"
|
|
|
+ "checkIn"
|
|
|
)
|
|
|
except Exception as e:
|
|
|
print(f"执行出错: {e}")
|
|
|
|
|
|
-
|
|
|
async def main():
|
|
|
keys = load_private_keys(KEY_FILE)
|
|
|
if not keys:
|
|
|
@@ -127,6 +116,5 @@ async def main():
|
|
|
await process_account(pk)
|
|
|
await asyncio.sleep(random.uniform(MIN_DELAY, MAX_DELAY))
|
|
|
|
|
|
-
|
|
|
if __name__ == "__main__":
|
|
|
- asyncio.run(main())
|
|
|
+ asyncio.run(main())
|