⸻
🔎 1️⃣ 事件检索(查询历史事件)
用 contract.queryFilter 可以查询链上已经发生的事件。
基本用法
const filter = contract.filters.Transfer(from, to); // ERC20 Transfer 事件示例
const events = await contract.queryFilter(filter, fromBlock, toBlock);
for (const event of events) {
console.log(event.args);
}
• contract.filters.MyEvent(arg1, arg2, ...) 会创建一个过滤器。
• fromBlock、toBlock 是区块高度,比如:
await contract.queryFilter(filter, 10000000, ‘latest’)
如果你只想查某个具体事件,可以用参数限制:
const filter = contract.filters.Transfer(“0xSenderAddress”, null); // 只过滤 from 地址
⸻
👂 2️⃣ 事件监听(实时监听新区块)
用 contract.on 或 contract.once。
持续监听
contract.on(“Transfer”, (from, to, value, event) => {
console.log(Transfer from ${from} to ${to} of ${value.toString()}
);
console.log(“Full event:”, event);
});
监听一次
contract.once(“Transfer”, (from, to, value, event) => {
console.log(Got one Transfer: ${from} -> ${to}
);
});
⸻
🔍 3️⃣ 事件过滤器
你可以直接用过滤器监听:
const filter = contract.filters.Transfer(null, “0xRecipientAddress”);
contract.on(filter, (from, to, value, event) => {
console.log(Filtered Transfer: ${from} -> ${to} (${value.toString()})
);
});
这样只会触发满足 to == 0xRecipientAddress 的 Transfer 事件。
⸻
🛠️ 4️⃣ 监听取消
如果要取消监听:
contract.off(“Transfer”, callback);
// 或
contract.removeAllListeners(“Transfer”);
如果你用了 filter,需要用同一个 filter 对象来取消:
contract.off(filter, callback);
⸻
🚀 小结
功能 方法
查询历史事件 contract.queryFilter
创建事件过滤器 contract.filters.XXX
实时监听事件 contract.on
只监听一次事件 contract.once
停止监听事件 contract.off / removeAllListeners
⸻
✍️ 小示例:完整监听与查询
import { ethers } from “ethers”;
const provider = new ethers.providers.JsonRpcProvider(“https://rpc-url”);
const contract = new ethers.Contract(contractAddress, abi, provider);
// 查询历史 Transfer 事件
const filter = contract.filters.Transfer(null, “0xRecipientAddress”);
const events = await contract.queryFilter(filter, 10000000, ‘latest’);
for (let e of events) {
console.log(“Past event:”, e.args);
}
// 监听未来 Transfer 事件
contract.on(filter, (from, to, value, event) => {
console.log(Realtime Transfer: ${from} -> ${to} (${value.toString()})
);
});
⸻
const provider = new ethers.providers.JsonRpcProvider(“https://rpc-url”);
我们逐步拆开详细解释一下。
⸻
📌 1️⃣ ethers.providers
在 ethers.js 里,ethers.providers 是用来和区块链节点(比如以太坊节点)通信的模块。
provider 就像是你的“区块链网关”:
• 读取链上的信息(余额、交易、区块、事件)
• 发送只读请求(比如 call)
• 监听新区块、事件
• 不负责签名(签名是由 Wallet 做的)
⸻
📌 2️⃣ JsonRpcProvider
ethers.providers.JsonRpcProvider 是最常用的 provider,直接通过 HTTP JSON-RPC 协议连接以太坊节点。
它可以连接:
• Infura / Alchemy 等公链服务商提供的 RPC
• 你自己搭建的 geth / besu / ganache 节点
• 或者 Hardhat / Foundry 的本地节点(比如 http://127.0.0.1:8545)
它内部就会自动帮你发送类似:
{
“jsonrpc”: “2.0”,
“method”: “eth_blockNumber”,
“params”: [],
“id”: 1
}
这种 JSON-RPC 请求,拿到链上数据。
⸻
📌 3️⃣ “https://rpc-url”
这是你指定的 RPC URL,例如:
• 主网 Infura:
new ethers.providers.JsonRpcProvider(“https://mainnet.infura.io/v3/your_project_id”)
• Sepolia 测试网:
new ethers.providers.JsonRpcProvider(“https://sepolia.infura.io/v3/your_project_id”)
• Hardhat 本地:
new ethers.providers.JsonRpcProvider(“http://127.0.0.1:8545”)
⸻
🔍 总结一句
const provider = new ethers.providers.JsonRpcProvider(“https://rpc-url”);
就是:
创建一个 provider 对象,让你可以通过 HTTP 请求这个 RPC 节点,读取链上的区块、交易、合约数据,监听事件等。
它只是一个「只读」入口,不带私钥,也不能签名交易。
如果要发起转账或执行合约写操作,要用 new ethers.Wallet(privateKey, provider) 来组合 signer。
⸻
✅ 要不要我再帮你写一个 provider + wallet 的示例,让你可以用私钥发交易?
需要的话说一声就写。 🚀