github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/model/events/parse.go (about)

     1  package events
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/onflow/flow-go/model/flow"
     8  )
     9  
    10  type ParsedEventType int
    11  
    12  const (
    13  	ProtocolEventType ParsedEventType = iota + 1
    14  	AccountEventType
    15  )
    16  
    17  type ParsedEvent struct {
    18  	Type         ParsedEventType
    19  	EventType    flow.EventType
    20  	Address      string
    21  	Contract     string
    22  	ContractName string
    23  	Name         string
    24  }
    25  
    26  // ParseEvent parses an event type into its parts. There are 2 valid EventType formats:
    27  // - flow.[EventName]
    28  // - A.[Address].[Contract].[EventName]
    29  // Any other format results in an error.
    30  func ParseEvent(eventType flow.EventType) (*ParsedEvent, error) {
    31  	parts := strings.Split(string(eventType), ".")
    32  
    33  	switch parts[0] {
    34  	case "flow":
    35  		if len(parts) == 2 {
    36  			return &ParsedEvent{
    37  				Type:         ProtocolEventType,
    38  				EventType:    eventType,
    39  				Contract:     parts[0],
    40  				ContractName: parts[0],
    41  				Name:         parts[1],
    42  			}, nil
    43  		}
    44  
    45  	case "A":
    46  		if len(parts) == 4 {
    47  			return &ParsedEvent{
    48  				Type:         AccountEventType,
    49  				EventType:    eventType,
    50  				Address:      parts[1],
    51  				Contract:     fmt.Sprintf("A.%s.%s", parts[1], parts[2]),
    52  				ContractName: parts[2],
    53  				Name:         parts[3],
    54  			}, nil
    55  		}
    56  	}
    57  
    58  	return nil, fmt.Errorf("invalid event type: %s", eventType)
    59  }
    60  
    61  // ValidateEvent validates an event type is properly formed and for the correct network, and returns
    62  // a parsed event. If the event type is invalid, an error is returned.
    63  func ValidateEvent(eventType flow.EventType, chain flow.Chain) (*ParsedEvent, error) {
    64  	parsed, err := ParseEvent(eventType)
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  
    69  	// only account type events have an address field
    70  	if parsed.Type != AccountEventType {
    71  		return parsed, nil
    72  	}
    73  
    74  	contractAddress := flow.HexToAddress(parsed.Address)
    75  	if !chain.IsValid(contractAddress) {
    76  		return nil, fmt.Errorf("invalid event contract address")
    77  	}
    78  
    79  	return parsed, nil
    80  }