第6节:解析事件

小白入门:https://github.com/dukedaily/solidity-expert ,欢迎star转发,文末加V入群。

职场进阶: https://dukeweb3.com

  • 本节适用于对历史数据进行过滤,处理,上一节适用于对新事件进行监听;
  • 对Data进行解析时,需要先构造对应的数据结构,用于存储数据;
  • Topic0就是事件的signature的hash值

    package main
    
    import (
     utils "code/main/utils"
       "context"
       "strings"
    
       "github.com/ethereum/go-ethereum/accounts/abi"
       "github.com/ethereum/go-ethereum/crypto"
    
       "fmt"
       "log"
       "math/big"
    
       "github.com/ethereum/go-ethereum"
       "github.com/ethereum/go-ethereum/common"
       "github.com/ethereum/go-ethereum/ethclient"
    
       store "code/src"
    )
    
    func main() {
       client, err := ethclient.Dial(utils.GoerliWSS)
       if err != nil {
           log.Fatal("Dial err:", err)
       }
    
       // 1. 准备合约地址
       contractAddr := "0xe4a220e0bd37673a90e2114abc98e4a22445c32e"
       address := common.HexToAddress(contractAddr)
    
       // 2. 构造过滤查询条件
       query := ethereum.FilterQuery{
           Addresses: []common.Address{address},
           FromBlock: new(big.Int).SetUint64(8059333),
           ToBlock:   new(big.Int).SetUint64(8059380),
       }
    
       // 3. 所有匹配的事件日志将存储在logs中
       // sub, err := client.SubscribeFilterLogs(context.Background(), query, logs)
       logs, err := client.FilterLogs(context.Background(), query)
       if err != nil {
           log.Fatal("FilterLogs err:", err)
       }
    
       contractAbi, err := abi.JSON(strings.NewReader(string(store.StoreABI)))
       if err != nil {
           log.Fatal(err)
       }
    
       for _, vLog := range logs {
           fmt.Println("find new event:")
           fmt.Println("\tblock hash:", vLog.BlockHash.Hex())
           fmt.Println("\tblock num :", vLog.BlockNumber)
           fmt.Println("\ttx   hash :", vLog.TxHash.Hex())
    
           // 解析Event中的Data
           event := struct {
               Key   [32]byte
               Value [32]byte
           }{}
    
       // 注意这里,与原文不一样,原文无法编译
       // err := contractAbi.Unpack(&event, "ItemSet", vLog.Data)
           err := contractAbi.UnpackIntoInterface(&event, "ItemSet", vLog.Data)
           if err != nil {
               log.Fatal(err)
           }
    
           fmt.Println("\tData:")
           fmt.Printf("\t\tkey  :%x\n", event.Key)
           fmt.Printf("\t\tvalue:%x\n", event.Value)
    
           // 解析Event中的Topic
           var topics [4]string
           fmt.Println("\tTopic:")
           for i := range vLog.Topics {
               topics[i] = vLog.Topics[i].Hex()
               fmt.Printf("\t\ttopic[%d]: %s\n", i, topics[i])
           }
       }
    
       eventSignature := []byte("ItemSet(address,bytes32,bytes32)")
       hash := crypto.Keccak256Hash(eventSignature)
       fmt.Println("topic hash:", hash.Hex())
    }
    

执行结果如下:

  • 成功解析事件中的Data数据
  • Topic0和事件的Signature的Hash值相同

image-20221202184051008