以太坊没有提供类似比特币根据地址查询历史交易的接口,因此在某些场景下(比如,币所用户充值)必须时刻监听着新生成的区块链里面是否包含平台用户的交易记录。针对此问题,以太坊有一个可以折中的JSON-RPC接口。
eth_newFilter接口可以创建一个filter对象,用来监听区块或交易发生的变化,也就所谓的日志(logs)。
主题(topic)是订单依赖的,当一条携带日志的交易在主题[A,B]之间,会被一下主题连接器所拦截: - [] 匹配任何交易; - [A] A之后的任何交易; - [null,B] B之前和之后的任何交易; - [A,B] A和B之间以及B之后的交易; - [[A,B],[A][B]] AB之间作为开始和AB之间作为结束,以及以后的交易;
params: [{
"fromBlock": "0x1",
"toBlock": "0x2",
"address": "0x8888f1f195afa192cfee860698584c030f4c9db1",
"topics": ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", null, ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b", "0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc"]]
}]
返回结果为filter的id。
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newFilter","params":[{"topics":["0x12341234"]}],"id":73}'
// Result
{
"id":1,
"jsonrpc": "2.0",
"result": "0x1" // 1
}
上面创建了filter,如果需要获取filter的变化信息还需要调用此接口进行查询。
此接口的参数就是上面接口返回的id。
返回的结果根据名字我们大家基本上就能知道大概的意思,此处不做过多解释,看一个具体的返回结果:
// Request
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0x16"],"id":73}'
// Result
{
"id":1,
"jsonrpc":"2.0",
"result": [{
"logIndex": "0x1", // 1
"blockNumber":"0x1b4" // 436
"blockHash": "0x8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcfdf829c5a142f1fccd7d",
"transactionHash": "0xdf829c5a142f1fccd7d8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcf",
"transactionIndex": "0x0", // 0
"address": "0x16c5785ac562ff41e2dcfdf829c5a142f1fccd7d",
"data":"0x0000000000000000000000000000000000000000000000000000000000000000",
"topics": ["0x59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a5"]
},{
...
}]
}
组合使用这两个接口,就可以实现监听某个地址的交易变化或新生成区块或交易。特别是对智能合约的执行的监听有很好的用武之地。
这也是本篇文章要引出的重点。如果说如何使用这两个接口看一下官方文档就可以轻易解决,但有些经验之谈就需要实践采坑之后才能获得。这里给大家分享几点实践中的经验。
在创建filter的时候,如果我们把fromBlock和toBlock设置的间隔特别长,比如从第一个块到最新块,那么启动程序之后要么会等待很久很久,要么直接抛出超时异常。
针对超时异常在可容忍的区块区间之中为了避免异常出现,可将超时时间设长。
针对pending交易的监听需要慎重,引入pending交易可能因为无法查到交易出现异常。
首先我们要明确一下,创建的filter其实是放在所链接的节点的内存当中,如果节点重启,那么对应的filter也就随之失效,节点重启之后需要重新创建filter,重新进行监听。
在使用的时候我们要明确一点,filter虽然可以设置fromBlock但是已经发生且不会变化的交易是无法通过eth_getFilterChanges获取到的。顾名思义,只有changes的交易才能获取到。比如监听在某个区块区间,这个区块区间的交易已经被打包确认,此时再创建filter,eth_getFilterChanges是无法拿到被打包确认的交易,只能获取到创建filter之后发生变化的交易。
因此,在实际使用的过程中要时刻注意filter是否存活。