Jack 4 meses atrás
pai
commit
7639a1ee49
1 arquivos alterados com 132 adições e 0 exclusões
  1. 132 0
      project/monad/of_apr_io_daily.py

+ 132 - 0
project/monad/of_apr_io_daily.py

@@ -0,0 +1,132 @@
+# -*- coding: utf-8 -*-
+"""
+Monad 测试网批量签到脚本(双合约版本)
+1. signIn()  → 0x9E1DDC2a90bc0bec6325dF48Cbb3125Ce2879F7C  方法 0x9e4cda43
+2. checkIn() → 0x703e753E9a2aCa1194DED65833EAec17dcFeAc1b  方法 0x183ff085
+"""
+
+import asyncio
+import os
+import random
+import time
+from typing import List
+
+from web3 import Web3
+from web3.types import TxReceipt
+
+# ------------------------ 用户配置区 ------------------------
+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 = 100000) -> int:
+    return base + random.randint(-5000, 10000)
+
+
+async def wait_tx(tx_hash: str) -> TxReceipt:
+    print(f"⏳ 等待交易确认: {tx_hash}")
+    receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=120)
+    if receipt.status == 1:
+        print("✅ 成功")
+    else:
+        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
+    balance = w3.eth.get_balance(addr)
+    if w3.from_wei(balance, "ether") < MIN_KEEP_BALANCE:
+        print(f"⚠️  {addr} 余额不足,跳过")
+        return
+
+    nonce = w3.eth.get_transaction_count(addr)
+    tx = {
+        "to": Web3.to_checksum_address(contract_addr),
+        "value": 0,
+        "data": selector,
+        "gas": random_gas_limit(),
+        "gasPrice": w3.eth.gas_price,
+        "nonce": nonce,
+        "chainId": w3.eth.chain_id,
+    }
+
+    signed = account.sign_transaction(tx)
+    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} ==========")
+
+    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))
+
+        # 2. checkIn
+        await send_contract_call(
+            private_key,
+            CHECK_IN_CONTRACT,
+            CHECK_IN_SELECTOR,
+            "2️⃣ checkIn"
+        )
+    except Exception as e:
+        print(f"执行出错: {e}")
+
+
+async def main():
+    keys = load_private_keys(KEY_FILE)
+    if not keys:
+        print("私钥文件为空")
+        return
+
+    print(f"共读取到 {len(keys)} 个钱包")
+    for pk in keys:
+        await process_account(pk)
+        await asyncio.sleep(random.uniform(MIN_DELAY, MAX_DELAY))
+
+
+if __name__ == "__main__":
+    asyncio.run(main())