github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/types/ibc-adapter/events.go (about)

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