You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Open-IM-Server/internal/rpc/redpacket/chain/parser.go

118 lines
2.5 KiB

package chain
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type ParsedEvent struct {
Name string
Data map[string]interface{}
TxHash common.Hash
BlockNumber uint64
}
func ParseEventsFromLogs(logs []*types.Log, contractABI abi.ABI) ([]*ParsedEvent, error) {
var events []*ParsedEvent
for _, log := range logs {
if len(log.Topics) == 0 {
continue
}
event, err := parseEvent(log, contractABI)
if err == nil && event != nil {
events = append(events, event)
}
}
return events, nil
}
func parseEvent(log *types.Log, contractABI abi.ABI) (*ParsedEvent, error) {
for name, event := range contractABI.Events {
if event.ID != log.Topics[0] {
continue
}
data := make(map[string]interface{})
indexedIdx := 1
for _, arg := range event.Inputs {
if arg.Indexed {
if indexedIdx < len(log.Topics) {
if arg.Type.T == abi.AddressTy {
data[arg.Name] = common.BytesToAddress(log.Topics[indexedIdx].Bytes())
} else if arg.Type.T == abi.UintTy || arg.Type.T == abi.IntTy {
data[arg.Name] = new(big.Int).SetBytes(log.Topics[indexedIdx].Bytes())
} else {
data[arg.Name] = log.Topics[indexedIdx].Hex()
}
indexedIdx++
}
}
}
if len(log.Data) > 0 {
unpacked, err := event.Inputs.Unpack(log.Data)
if err == nil {
nonIndexedIdx := 0
for _, arg := range event.Inputs {
if !arg.Indexed {
if nonIndexedIdx < len(unpacked) {
data[arg.Name] = unpacked[nonIndexedIdx]
nonIndexedIdx++
}
}
}
}
}
return &ParsedEvent{
Name: name,
Data: data,
TxHash: log.TxHash,
BlockNumber: log.BlockNumber,
}, nil
}
return nil, fmt.Errorf("unknown event: %s", log.Topics[0].Hex())
}
func GetPacketIDFromEvent(event *ParsedEvent) *big.Int {
if id, ok := event.Data["packetId"]; ok {
if b, ok := id.(*big.Int); ok {
return b
}
}
return big.NewInt(0)
}
func GetAddressFromEvent(event *ParsedEvent, key string) common.Address {
value, ok := event.Data[key]
if !ok {
return common.Address{}
}
addr, _ := value.(common.Address)
return addr
}
func GetAmountFromEvent(event *ParsedEvent) *big.Int {
return GetUintFromEvent(event, "amount")
}
func GetUintFromEvent(event *ParsedEvent, key string) *big.Int {
value, ok := event.Data[key]
if !ok {
return big.NewInt(0)
}
if b, ok := value.(*big.Int); ok {
return b
}
return big.NewInt(0)
}