Skip to content

Commit

Permalink
feat: filterable event streaming
Browse files Browse the repository at this point in the history
  • Loading branch information
seanmcgary committed Feb 4, 2025
1 parent 67e3f1a commit 22a6f53
Show file tree
Hide file tree
Showing 11 changed files with 1,156 additions and 17 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/DataDog/datadog-go/v5 v5.5.0
github.com/Layr-Labs/eigenlayer-contracts v0.4.1-holesky-pepe.0.20240813143901-00fc4b95e9c1
github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.13
github.com/Layr-Labs/protocol-apis v1.3.0
github.com/Layr-Labs/protocol-apis v1.3.1-0.20250130210204-01700dca3998
github.com/ethereum/go-ethereum v1.14.9
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1
github.com/google/uuid v1.6.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.13 h1:Blb4AE+jC/vddV71w4/MQA
github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.13/go.mod h1:PD/HoyzZjxDw1tAcZw3yD0yGddo+yhmwQAi+lk298r4=
github.com/Layr-Labs/protocol-apis v1.3.0 h1:T0HjCEYc3ez3FMx9EP8YiLzsszYn0ccfSlHtuqTu2SA=
github.com/Layr-Labs/protocol-apis v1.3.0/go.mod h1:prNA2/mLO5vpMZ2q78Nsn0m97wm28uiRnwO+/yOxigk=
github.com/Layr-Labs/protocol-apis v1.3.1-0.20250130210204-01700dca3998 h1:DGFSld0GaiYPHpjXzD9fYHRgVAdeuulftWNtLaipBd0=
github.com/Layr-Labs/protocol-apis v1.3.1-0.20250130210204-01700dca3998/go.mod h1:prNA2/mLO5vpMZ2q78Nsn0m97wm28uiRnwO+/yOxigk=
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
Expand Down
197 changes: 197 additions & 0 deletions pkg/eventFilter/condition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package eventFilter

import (
"encoding/json"
"fmt"
)

// Condition represents a single filter condition
type Condition struct {
Field string `json:"-"`
Op Operator `json:"-"`
Value interface{} `json:"-"`
EntType EntityType `json:"-"`
}

func (c *Condition) Type() string {
return "condition"
}

func (c *Condition) ToFilterJSON() (FilterJSON, error) {
return FilterJSON{
Type: c.Type(),
Field: c.Field,
Operator: c.Op.String(),
Value: c.Value,
EntType: c.EntType.String(),
}, nil
}

func (c *Condition) MarshalJSON() ([]byte, error) {
fj, err := c.ToFilterJSON()
if err != nil {
return nil, err
}
return json.Marshal(fj)
}

func (c *Condition) UnmarshalJSON(data []byte) error {
var f FilterJSON
if err := json.Unmarshal(data, &f); err != nil {
return err
}

c.Field = f.Field
c.Value = f.Value
c.EntType = EntityType(f.EntType)
c.Op = ParseOperator(f.Operator)

return nil
}

func (c *Condition) Evaluate(entity interface{}, registry *FilterableRegistry) (bool, error) {
// Validate entity type
if err := registry.ValidateEntityType(c.EntType, entity); err != nil {
return false, err
}

fieldValue, err := registry.GetFilterableField(entity, c.Field)
if err != nil {
return false, err
}

return compare(fieldValue, c.Op, c.Value)
}

// And combines multiple filters with AND logic
type And struct {
Filters []Filter
}

func (a *And) ToFilterJSON() (FilterJSON, error) {
filters := make([]FilterJSON, len(a.Filters))
for i, f := range a.Filters {
fj, err := f.ToFilterJSON()
if err != nil {
return FilterJSON{}, err
}
filters[i] = fj
}

return FilterJSON{
Type: a.Type(),
Filters: filters,
}, nil
}

func (a *And) MarshalJSON() ([]byte, error) {
fj, err := a.ToFilterJSON()
if err != nil {
return nil, err
}
return json.Marshal(fj)
}

func (a *And) UnmarshalJSON(data []byte) error {
var filterJSON FilterJSON
if err := json.Unmarshal(data, &filterJSON); err != nil {
return err
}

filters := make([]Filter, len(filterJSON.Filters))
for i, f := range filterJSON.Filters {
filter, err := ParseFilter(f)
if err != nil {
return err
}
filters[i] = filter
}

a.Filters = filters
return nil
}

func (a *And) Evaluate(entity interface{}, registry *FilterableRegistry) (bool, error) {
for _, filter := range a.Filters {
result, err := filter.Evaluate(entity, registry)
fmt.Printf("And eval: [] [] %+v\n", result)
if err != nil {
return false, err
}
if !result {
return false, nil
}
}
return true, nil
}

func (a *And) Type() string {
return "and"
}

// Or combines multiple filters with OR logic
type Or struct {
Filters []Filter
}

func (o *Or) ToFilterJSON() (FilterJSON, error) {
filters := make([]FilterJSON, len(o.Filters))
for i, f := range o.Filters {
fj, err := f.ToFilterJSON()
if err != nil {
return FilterJSON{}, err
}
filters[i] = fj
}

return FilterJSON{
Type: o.Type(),
Filters: filters,
}, nil
}

func (o *Or) MarshalJSON() ([]byte, error) {
fj, err := o.ToFilterJSON()
if err != nil {
return nil, err
}
return json.Marshal(fj)
}

func (o *Or) UnmarshalJSON(data []byte) error {
var filterJSON FilterJSON
if err := json.Unmarshal(data, &filterJSON); err != nil {
return err
}

filters := make([]Filter, len(filterJSON.Filters))
for i, f := range filterJSON.Filters {
filter, err := ParseFilter(f)
if err != nil {
return err
}
filters[i] = filter
}

o.Filters = filters
return nil
}

func (o *Or) Type() string {
return Condition_OR
}

func (o *Or) Evaluate(entity interface{}, registry *FilterableRegistry) (bool, error) {
fmt.Printf("Or list length: %+v\n", len(o.Filters))
for _, filter := range o.Filters {
result, err := filter.Evaluate(entity, registry)
fmt.Printf("Or eval: err: %+v - %+v\n", err, result)
if err != nil {
return false, err
}
if result {
return true, nil
}
}
return false, nil
}
21 changes: 21 additions & 0 deletions pkg/eventFilter/eventTypeRegistry/registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package eventTypeRegistry

import (
"github.com/Layr-Labs/sidecar/pkg/eventFilter"
"github.com/Layr-Labs/sidecar/pkg/storage"
)

func BuildFilterableEventRegistry() (*eventFilter.FilterableRegistry, error) {
reg := eventFilter.NewFilterableRegistry()
if err := reg.RegisterType(&storage.Block{}); err != nil {
return nil, err
}
if err := reg.RegisterType(&storage.Transaction{}); err != nil {
return nil, err
}
if err := reg.RegisterType(&storage.TransactionLog{}); err != nil {
return nil, err
}

return reg, nil
}
Loading

0 comments on commit 22a6f53

Please sign in to comment.