为了订阅事件日志,我们需要做的第一件事就是拨打启用websocket的以太坊客户端。 幸运的是,Infura支持websockets。
client, err := ethclient.Dial("wss://rinkeby.infura.io/ws")if err != nil {log.Fatal(err)}
下一步是创建筛选查询。 在这个例子中,我们将阅读来自我们在之前课程中创建的示例合约中的所有事件。
contractAddress := common.HexToAddress("0x147B8eb97fD247D06C4006D269c90C1908Fb5D54")query := ethereum.FilterQuery{Addresses: []common.Address{contractAddress},}
我们接收事件的方式是通过Go channel。 让我们从go-ethereumcore/types包创建一个类型为Log的channel。
logs := make(chan types.Log)
现在我们所要做的就是通过从客户端调用SubscribeFilterLogs来订阅,它接收查询选项和输出通道。 这将返回包含unsubscribe和error方法的订阅结构。
sub, err := client.SubscribeFilterLogs(context.Background(), query, logs)if err != nil {log.Fatal(err)}
最后,我们要做的就是使用select语句设置一个连续循环来读入新的日志事件或订阅错误。
for {select {case err := <-sub.Err():log.Fatal(err)case vLog := <-logs:fmt.Println(vLog) // pointer to event log}}
我们会在下个章节介绍如何解析日志。
完整代码
Commands
solc --abi Store.solsolc --bin Store.solabigen --bin=Store_sol_Store.bin --abi=Store_sol_Store.abi --pkg=store --out=Store.go
pragma solidity ^0.4.24;contract Store {event ItemSet(bytes32 key, bytes32 value);string public version;mapping (bytes32 => bytes32) public items;constructor(string _version) public {version = _version;}function setItem(bytes32 key, bytes32 value) external {items[key] = value;emit ItemSet(key, value);}}
package mainimport ("context""fmt""log""github.com/ethereum/go-ethereum""github.com/ethereum/go-ethereum/common""github.com/ethereum/go-ethereum/core/types""github.com/ethereum/go-ethereum/ethclient")func main() {client, err := ethclient.Dial("wss://rinkeby.infura.io/ws")if err != nil {log.Fatal(err)}contractAddress := common.HexToAddress("0x147B8eb97fD247D06C4006D269c90C1908Fb5D54")query := ethereum.FilterQuery{Addresses: []common.Address{contractAddress},}logs := make(chan types.Log)sub, err := client.SubscribeFilterLogs(context.Background(), query, logs)if err != nil {log.Fatal(err)}for {select {case err := <-sub.Err():log.Fatal(err)case vLog := <-logs:fmt.Println(vLog) // pointer to event log}}}
