github.com/Finschia/finschia-sdk@v0.48.1/types/events.go (about)

     1  package types
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"reflect"
     7  	"sort"
     8  	"strings"
     9  
    10  	"golang.org/x/exp/maps"
    11  	"golang.org/x/exp/slices"
    12  
    13  	"github.com/gogo/protobuf/jsonpb"
    14  	proto "github.com/gogo/protobuf/proto"
    15  	abci "github.com/tendermint/tendermint/abci/types"
    16  
    17  	"github.com/Finschia/finschia-sdk/codec"
    18  )
    19  
    20  // ----------------------------------------------------------------------------
    21  // Event Manager
    22  // ----------------------------------------------------------------------------
    23  
    24  // EventManager implements a simple wrapper around a slice of Event objects that
    25  // can be emitted from.
    26  type EventManager struct {
    27  	events Events
    28  }
    29  
    30  func NewEventManager() *EventManager {
    31  	return &EventManager{EmptyEvents()}
    32  }
    33  
    34  func (em *EventManager) Events() Events { return em.events }
    35  
    36  // EmitEvent stores a single Event object.
    37  // Deprecated: Use EmitTypedEvent
    38  func (em *EventManager) EmitEvent(event Event) {
    39  	em.events = em.events.AppendEvent(event)
    40  }
    41  
    42  // EmitEvents stores a series of Event objects.
    43  // Deprecated: Use EmitTypedEvents
    44  func (em *EventManager) EmitEvents(events Events) {
    45  	em.events = em.events.AppendEvents(events)
    46  }
    47  
    48  // ABCIEvents returns all stored Event objects as abci.Event objects.
    49  func (em EventManager) ABCIEvents() []abci.Event {
    50  	return em.events.ToABCIEvents()
    51  }
    52  
    53  // EmitTypedEvent takes typed event and emits converting it into Event
    54  func (em *EventManager) EmitTypedEvent(tev proto.Message) error {
    55  	event, err := TypedEventToEvent(tev)
    56  	if err != nil {
    57  		return err
    58  	}
    59  
    60  	em.EmitEvent(event)
    61  	return nil
    62  }
    63  
    64  // EmitTypedEvents takes series of typed events and emit
    65  func (em *EventManager) EmitTypedEvents(tevs ...proto.Message) error {
    66  	events := make(Events, len(tevs))
    67  	for i, tev := range tevs {
    68  		res, err := TypedEventToEvent(tev)
    69  		if err != nil {
    70  			return err
    71  		}
    72  		events[i] = res
    73  	}
    74  
    75  	em.EmitEvents(events)
    76  	return nil
    77  }
    78  
    79  // TypedEventToEvent takes typed event and converts to Event object
    80  func TypedEventToEvent(tev proto.Message) (Event, error) {
    81  	evtType := proto.MessageName(tev)
    82  	evtJSON, err := codec.ProtoMarshalJSON(tev, nil)
    83  	if err != nil {
    84  		return Event{}, err
    85  	}
    86  
    87  	var attrMap map[string]json.RawMessage
    88  	err = json.Unmarshal(evtJSON, &attrMap)
    89  	if err != nil {
    90  		return Event{}, err
    91  	}
    92  
    93  	// sort the keys to ensure the order is always the same
    94  	keys := maps.Keys(attrMap)
    95  	slices.Sort(keys)
    96  
    97  	attrs := make([]abci.EventAttribute, 0, len(attrMap))
    98  	for _, k := range keys {
    99  		v := attrMap[k]
   100  		attrs = append(attrs, abci.EventAttribute{
   101  			Key:   []byte(k),
   102  			Value: v,
   103  		})
   104  	}
   105  
   106  	return Event{
   107  		Type:       evtType,
   108  		Attributes: attrs,
   109  	}, nil
   110  }
   111  
   112  // ParseTypedEvent converts abci.Event back to typed event
   113  func ParseTypedEvent(event abci.Event) (proto.Message, error) {
   114  	concreteGoType := proto.MessageType(event.Type)
   115  	if concreteGoType == nil {
   116  		return nil, fmt.Errorf("failed to retrieve the message of type %q", event.Type)
   117  	}
   118  
   119  	var value reflect.Value
   120  	if concreteGoType.Kind() == reflect.Ptr {
   121  		value = reflect.New(concreteGoType.Elem())
   122  	} else {
   123  		value = reflect.Zero(concreteGoType)
   124  	}
   125  
   126  	protoMsg, ok := value.Interface().(proto.Message)
   127  	if !ok {
   128  		return nil, fmt.Errorf("%q does not implement proto.Message", event.Type)
   129  	}
   130  
   131  	attrMap := make(map[string]json.RawMessage)
   132  	for _, attr := range event.Attributes {
   133  		attrMap[string(attr.Key)] = attr.Value
   134  	}
   135  
   136  	attrBytes, err := json.Marshal(attrMap)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	err = jsonpb.Unmarshal(strings.NewReader(string(attrBytes)), protoMsg)
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  
   146  	return protoMsg, nil
   147  }
   148  
   149  // ----------------------------------------------------------------------------
   150  // Events
   151  // ----------------------------------------------------------------------------
   152  
   153  type (
   154  	// Event is a type alias for an ABCI Event
   155  	Event abci.Event
   156  
   157  	// Events defines a slice of Event objects
   158  	Events []Event
   159  )
   160  
   161  // NewEvent creates a new Event object with a given type and slice of one or more
   162  // attributes.
   163  func NewEvent(ty string, attrs ...Attribute) Event {
   164  	e := Event{Type: ty}
   165  
   166  	for _, attr := range attrs {
   167  		e.Attributes = append(e.Attributes, attr.ToKVPair())
   168  	}
   169  
   170  	return e
   171  }
   172  
   173  // NewAttribute returns a new key/value Attribute object.
   174  func NewAttribute(k, v string) Attribute {
   175  	return Attribute{k, v}
   176  }
   177  
   178  // EmptyEvents returns an empty slice of events.
   179  func EmptyEvents() Events {
   180  	return make(Events, 0)
   181  }
   182  
   183  func (a Attribute) String() string {
   184  	return fmt.Sprintf("%s: %s", a.Key, a.Value)
   185  }
   186  
   187  // ToKVPair converts an Attribute object into a Tendermint key/value pair.
   188  func (a Attribute) ToKVPair() abci.EventAttribute {
   189  	return abci.EventAttribute{Key: toBytes(a.Key), Value: toBytes(a.Value)}
   190  }
   191  
   192  // AppendAttributes adds one or more attributes to an Event.
   193  func (e Event) AppendAttributes(attrs ...Attribute) Event {
   194  	for _, attr := range attrs {
   195  		e.Attributes = append(e.Attributes, attr.ToKVPair())
   196  	}
   197  	return e
   198  }
   199  
   200  // GetAttribute returns an attribute for a given key present in an event.
   201  // If the key is not found, the boolean value will be false.
   202  func (e Event) GetAttribute(key string) (Attribute, bool) {
   203  	for _, attr := range e.Attributes {
   204  		if string(attr.Key) == key {
   205  			return Attribute{Key: string(attr.Key), Value: string(attr.Value)}, true
   206  		}
   207  	}
   208  	return Attribute{}, false
   209  }
   210  
   211  // AppendEvent adds an Event to a slice of events.
   212  func (e Events) AppendEvent(event Event) Events {
   213  	return append(e, event)
   214  }
   215  
   216  // AppendEvents adds a slice of Event objects to an exist slice of Event objects.
   217  func (e Events) AppendEvents(events Events) Events {
   218  	return append(e, events...)
   219  }
   220  
   221  // ToABCIEvents converts a slice of Event objects to a slice of abci.Event
   222  // objects.
   223  func (e Events) ToABCIEvents() []abci.Event {
   224  	res := make([]abci.Event, len(e))
   225  	for i, ev := range e {
   226  		res[i] = abci.Event{Type: ev.Type, Attributes: ev.Attributes}
   227  	}
   228  
   229  	return res
   230  }
   231  
   232  func toBytes(i interface{}) []byte {
   233  	switch x := i.(type) {
   234  	case []uint8:
   235  		return x
   236  	case string:
   237  		return []byte(x)
   238  	default:
   239  		panic(i)
   240  	}
   241  }
   242  
   243  // GetAttributes returns all attributes matching a given key present in events.
   244  // If the key is not found, the boolean value will be false.
   245  func (e Events) GetAttributes(key string) ([]Attribute, bool) {
   246  	attrs := make([]Attribute, 0)
   247  	for _, event := range e {
   248  		if attr, found := event.GetAttribute(key); found {
   249  			attrs = append(attrs, attr)
   250  		}
   251  	}
   252  
   253  	return attrs, len(attrs) > 0
   254  }
   255  
   256  // Common event types and attribute keys
   257  const (
   258  	EventTypeTx = "tx"
   259  
   260  	AttributeKeyAccountSequence = "acc_seq"
   261  	AttributeKeySignature       = "signature"
   262  	AttributeKeyFee             = "fee"
   263  	AttributeKeyFeePayer        = "fee_payer"
   264  
   265  	EventTypeMessage = "message"
   266  
   267  	AttributeKeyAction = "action"
   268  	AttributeKeyModule = "module"
   269  	AttributeKeySender = "sender"
   270  	AttributeKeyAmount = "amount"
   271  )
   272  
   273  type (
   274  	// StringAttributes defines a slice of StringEvents objects.
   275  	StringEvents []StringEvent
   276  )
   277  
   278  func (se StringEvents) String() string {
   279  	var sb strings.Builder
   280  
   281  	for _, e := range se {
   282  		sb.WriteString(fmt.Sprintf("\t\t- %s\n", e.Type))
   283  
   284  		for _, attr := range e.Attributes {
   285  			sb.WriteString(fmt.Sprintf("\t\t\t- %s\n", attr.String()))
   286  		}
   287  	}
   288  
   289  	return strings.TrimRight(sb.String(), "\n")
   290  }
   291  
   292  // Flatten returns a flattened version of StringEvents by grouping all attributes
   293  // per unique event type.
   294  func (se StringEvents) Flatten() StringEvents {
   295  	flatEvents := make(map[string][]Attribute)
   296  
   297  	for _, e := range se {
   298  		flatEvents[e.Type] = append(flatEvents[e.Type], e.Attributes...)
   299  	}
   300  	keys := make([]string, 0, len(flatEvents))
   301  	res := make(StringEvents, 0, len(flatEvents)) // appeneded to keys, same length of what is allocated to keys
   302  
   303  	for ty := range flatEvents {
   304  		keys = append(keys, ty)
   305  	}
   306  
   307  	sort.Strings(keys)
   308  	for _, ty := range keys {
   309  		res = append(res, StringEvent{Type: ty, Attributes: flatEvents[ty]})
   310  	}
   311  
   312  	return res
   313  }
   314  
   315  // StringifyEvent converts an Event object to a StringEvent object.
   316  func StringifyEvent(e abci.Event) StringEvent {
   317  	res := StringEvent{Type: e.Type}
   318  
   319  	for _, attr := range e.Attributes {
   320  		res.Attributes = append(
   321  			res.Attributes,
   322  			Attribute{string(attr.Key), string(attr.Value)},
   323  		)
   324  	}
   325  
   326  	return res
   327  }
   328  
   329  // StringifyEvents converts a slice of Event objects into a slice of StringEvent
   330  // objects.
   331  func StringifyEvents(events []abci.Event) StringEvents {
   332  	res := make(StringEvents, 0, len(events))
   333  
   334  	for _, e := range events {
   335  		res = append(res, StringifyEvent(e))
   336  	}
   337  
   338  	return res.Flatten()
   339  }
   340  
   341  // MarkEventsToIndex returns the set of ABCI events, where each event's attribute
   342  // has it's index value marked based on the provided set of events to index.
   343  func MarkEventsToIndex(events []abci.Event, indexSet map[string]struct{}) []abci.Event {
   344  	indexAll := len(indexSet) == 0
   345  	updatedEvents := make([]abci.Event, len(events))
   346  
   347  	for i, e := range events {
   348  		updatedEvent := abci.Event{
   349  			Type:       e.Type,
   350  			Attributes: make([]abci.EventAttribute, len(e.Attributes)),
   351  		}
   352  
   353  		for j, attr := range e.Attributes {
   354  			_, index := indexSet[fmt.Sprintf("%s.%s", e.Type, attr.Key)]
   355  			updatedAttr := abci.EventAttribute{
   356  				Key:   attr.Key,
   357  				Value: attr.Value,
   358  				Index: index || indexAll,
   359  			}
   360  
   361  			updatedEvent.Attributes[j] = updatedAttr
   362  		}
   363  
   364  		updatedEvents[i] = updatedEvent
   365  	}
   366  
   367  	return updatedEvents
   368  }