以太坊地址监控收官:Python 实战心得与避坑指南

·

🏁 这是以太坊地址监控系列的最后一篇,前三篇已分别讲述基础调用、区块监听与 Token 变动捕捉。本文聚焦 Python 重构后的最终落地经验,帮你避开作者踩过的坑,并给出可直接复用的代码片段。

为什么选择 Web3.py 重构?

早期版本直接用 requests 发 HTTP 调用,代码量大、调试痛苦、格式不统一。作者尝试过:

核心关键词:web3.pyPython 以太坊开发地址监听智能合约监听


三大核心对象拆解

EthAddrWatcher:监控以太币流动

职责一目了然:

关键示例

watcher = EthAddrWatcher(endpoint="https://mainnet.infura.io/v3/YOUR_KEY")
watcher.add_address("0xA0b86a33E6441b0...")   # 关注热钱包
watcher.on_balance_change(lambda addr, delta: 
    print(f"{addr} 金额变动 {Web3.from_wei(delta,'ether')} ETH"))

watcher.loop_forever()

EthAddrWatcherDB:把变更写进 DB

将增量数据落表,防止 窗口宕机漏数。选型简单暴力:

关键词:数据库监听表、SQLite、增量落库。

EthBlockSrv:命令行守护进程

一条命令拉起:

python eth_block_srv.py --conf /etc/eth_watcher.yaml

四大雷区 & 避坑清单

1. 合约销毁后 getCode() 返回 0x

现象:
调用 w3.eth.get_code(contract_addr) 得到空字符串,于是脚本将其误判为普通 EOA(内部账户)。
解决思路:查看该地址历史交易 input 字段,只要存在 SELFDESTRUCT 操作即可断定已销毁,无需额外判断 合约接口是否存在

核心关键词:以太坊合约销毁、SELFDESTRUCTgetCode

2. 地址大小写不敏感却暗坑

测试网转账两次:

to=0x068a7A0022a0e20d78682F39aA75547A0A260A2A  // 大写A
to=0x068a7A0022a0e20d78682F39aA75547A0A260A2a  // 小写a

结果链上都解析成 同一个收款地址。但 off-chain 工具却严格区分大小写,数据库唯一索引会崩溃。

对策:

3. 主网 getCode() 意外返回 0x

哪怕地址明显是合约,偶尔也会拿到 0x
作者调试 3 小时发现:Infura 节点延迟导致调用命中空缓存。方案:

4. 节点未同步,blockNumbersyncing 均取不到

--syncmode fast 的节点下,偶发的网络抖动会触发:

哈克方法:

  1. 循环等待 1 秒;
  2. 设置最大重试阈值 120;
  3. 达到阈值直接报警,防止脚本假死

独立可运行最小示例

把核心流程压缩到 50 行,供同行快速测试(Python 3.9+):

from web3 import Web3, HTTPProvider
import sqlite3, time, os

w = Web3(HTTPProvider('https://mainnet.infura.io/v3/KEY'))
conn = sqlite3.connect('addr_watch.db')
addr = Web3.to_checksum_address('0x...')
cursor = conn.execute('SELECT balance FROM accounts WHERE address=?', (addr,))
old = int(cursor.fetchone()[0]) if cursor.arraysize > 0 else 0

while True:
    try:
        new = w.eth.get_balance(addr)
        if new != old:
            conn.execute('INSERT OR REPLACE INTO accounts(address,balance) VALUES (?,?)',
                         (addr, new))
            conn.commit()
            print('余额变化:', (new-old)/1e18, 'ETH')
            old = new
        time.sleep(5)
    except Exception as e:
        print('重连中', e)
        time.sleep(1)

关键词:Python 脚本 实时轮询余额、轻量级架构。


常见问题与解答(FAQ)

为什么我调用 eth_getBalance 一直在变?如果同一地址有未打包交易,RPC 节点可能在 Pending 状态确认状态 间波动。给 block_identifier="latest" 再加 1 个确认即可。
Infura 免费套餐够地址监控吗?每天 100k 次调用,仅监控几十地址完全够用。一旦调用量上涨,自建 geth light 节点 每月成本 <5 美元。
如何区分 ERC-20 转账与普通转账?tx.input 长度 ≥ 10 且前 10 位为 0xa9059cbb,大概率是 ERC-20 的 transfer(address,uint256),可据此再解码 tovalue
SQLite 写入并发会阻塞吗?官方 WAL 模式已解决并发写。配合 check_same_thread=False 在 Python 中即可,多个 watchdog 进程同时写无明显锁表。
我还能监控哪些参数?除余额与 Token 流向外,还可以拉取 Nonce 变动、Gas Price 波动、智能事件日志——只需把 EthBlockSrv 解耦成插件式架构即可。

下一步计划


关键词一览(自然融入文中)


如果你觉得这套代码对你有帮助,欢迎 Star & Fork(去 Github 搜索同名主题即可)。更多优化细节,未来也会持续分享到社区~