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