From e56b47af557838deefa6936e8f76455a7c89c061 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 20 Jun 2023 15:58:04 -0700 Subject: [PATCH 1/2] add get events by address/name param for community --- .../eventindexer/contracts/taikol1/TaikoL1.go | 12 ++-- packages/eventindexer/event.go | 5 ++ .../http/get_by_address_and_event.go | 28 ++++++++ .../http/get_by_address_and_event_test.go | 68 +++++++++++++++++++ packages/eventindexer/http/routes.go | 1 + .../eventindexer/mock/event_repository.go | 16 +++++ packages/eventindexer/repo/event.go | 16 +++++ packages/eventindexer/repo/event_test.go | 54 +++++++++++++++ 8 files changed, 194 insertions(+), 6 deletions(-) create mode 100644 packages/eventindexer/http/get_by_address_and_event.go create mode 100644 packages/eventindexer/http/get_by_address_and_event_test.go diff --git a/packages/eventindexer/contracts/taikol1/TaikoL1.go b/packages/eventindexer/contracts/taikol1/TaikoL1.go index 8fed2caf9e..93ab021044 100644 --- a/packages/eventindexer/contracts/taikol1/TaikoL1.go +++ b/packages/eventindexer/contracts/taikol1/TaikoL1.go @@ -8,12 +8,12 @@ import ( "math/big" "strings" - ethereum "github.com/taikochain/go-taiko" - "github.com/taikochain/go-taiko/accounts/abi" - "github.com/taikochain/go-taiko/accounts/abi/bind" - "github.com/taikochain/go-taiko/common" - "github.com/taikochain/go-taiko/core/types" - "github.com/taikochain/go-taiko/event" + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" ) // Reference imports to suppress errors if they are not otherwise used. diff --git a/packages/eventindexer/event.go b/packages/eventindexer/event.go index 66fd1a68ad..15922fb212 100644 --- a/packages/eventindexer/event.go +++ b/packages/eventindexer/event.go @@ -65,4 +65,9 @@ type EventRepository interface { id int, ) error GetCountByAddressAndEventName(ctx context.Context, address string, event string) (int, error) + GetByAddressAndEventName( + ctx context.Context, + address string, + event string, + ) ([]*Event, error) } diff --git a/packages/eventindexer/http/get_by_address_and_event.go b/packages/eventindexer/http/get_by_address_and_event.go new file mode 100644 index 0000000000..7cf700edf3 --- /dev/null +++ b/packages/eventindexer/http/get_by_address_and_event.go @@ -0,0 +1,28 @@ +package http + +import ( + "net/http" + + "github.com/cyberhorsey/webutils" + "github.com/labstack/echo/v4" + "github.com/taikoxyz/taiko-mono/packages/eventindexer" +) + +type GetByAddressAndEventNameResp struct { + Events []*eventindexer.Event `json:"events"` +} + +func (srv *Server) GetByAddressAndEventName(c echo.Context) error { + events, err := srv.eventRepo.GetByAddressAndEventName( + c.Request().Context(), + c.QueryParam("address"), + c.QueryParam("event"), + ) + if err != nil { + return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, err) + } + + return c.JSON(http.StatusOK, &GetByAddressAndEventNameResp{ + Events: events, + }) +} diff --git a/packages/eventindexer/http/get_by_address_and_event_test.go b/packages/eventindexer/http/get_by_address_and_event_test.go new file mode 100644 index 0000000000..309307c1b2 --- /dev/null +++ b/packages/eventindexer/http/get_by_address_and_event_test.go @@ -0,0 +1,68 @@ +package http + +import ( + "context" + "fmt" + "math/big" + "net/http" + "net/http/httptest" + "testing" + + "github.com/cyberhorsey/webutils/testutils" + "github.com/labstack/echo/v4" + "github.com/stretchr/testify/assert" + "github.com/taikoxyz/taiko-mono/packages/eventindexer" +) + +func Test_GetByAddressAndEvent(t *testing.T) { + srv := newTestServer("") + + _, err := srv.eventRepo.Save(context.Background(), eventindexer.SaveEventOpts{ + Name: "name", + Data: `{"Owner": "0x0000000000000000000000000000000000000123"}`, + ChainID: big.NewInt(167001), + Address: "0x123", + Event: eventindexer.EventNameBlockProposed, + }) + + assert.Equal(t, nil, err) + + tests := []struct { + name string + address string + event string + wantStatus int + wantBodyRegexpMatches []string + }{ + { + "successZeroEvents", + "0xhasntProposedAnything", + eventindexer.EventNameBlockProposed, + http.StatusOK, + []string{`{"events":`}, + }, + { + "success", + "0x123", + eventindexer.EventNameBlockProposed, + http.StatusOK, + []string{`{"events":`}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + req := testutils.NewUnauthenticatedRequest( + echo.GET, + fmt.Sprintf("/events?address=%v&event=%v", tt.address, tt.event), + nil, + ) + + rec := httptest.NewRecorder() + + srv.ServeHTTP(rec, req) + + testutils.AssertStatusAndBody(t, rec, tt.wantStatus, tt.wantBodyRegexpMatches) + }) + } +} diff --git a/packages/eventindexer/http/routes.go b/packages/eventindexer/http/routes.go index 30a3aee777..8c0f1620b5 100644 --- a/packages/eventindexer/http/routes.go +++ b/packages/eventindexer/http/routes.go @@ -7,5 +7,6 @@ func (srv *Server) configureRoutes() { srv.echo.GET("/uniqueProvers", srv.GetUniqueProvers) srv.echo.GET("/uniqueProposers", srv.GetUniqueProposers) srv.echo.GET("/eventByAddress", srv.GetCountByAddressAndEventName) + srv.echo.GET("/events", srv.GetByAddressAndEventName) srv.echo.GET("/stats", srv.GetStats) } diff --git a/packages/eventindexer/mock/event_repository.go b/packages/eventindexer/mock/event_repository.go index 6e27422863..a3a1c6ea88 100644 --- a/packages/eventindexer/mock/event_repository.go +++ b/packages/eventindexer/mock/event_repository.go @@ -59,6 +59,22 @@ func (r *EventRepository) GetCountByAddressAndEventName( return count, nil } +func (r *EventRepository) GetByAddressAndEventName( + ctx context.Context, + address string, + event string, +) ([]*eventindexer.Event, error) { + var events []*eventindexer.Event + + for _, e := range r.events { + if e.Address == address && e.Event == event { + events = append(events, e) + } + } + + return events, nil +} + func (r *EventRepository) FindByEventTypeAndBlockID( ctx context.Context, eventType string, diff --git a/packages/eventindexer/repo/event.go b/packages/eventindexer/repo/event.go index 2ce163a4d5..5a51cb1dcf 100644 --- a/packages/eventindexer/repo/event.go +++ b/packages/eventindexer/repo/event.go @@ -112,3 +112,19 @@ func (r *EventRepository) GetCountByAddressAndEventName( return count, nil } + +func (r *EventRepository) GetByAddressAndEventName( + ctx context.Context, + address string, + event string, +) ([]*eventindexer.Event, error) { + var events []*eventindexer.Event + + if err := r.db.GormDB(). + Raw("SELECT * FROM events WHERE event = ? AND address = ?", event, address). + Find(&events).Error; err != nil { + return nil, errors.Wrap(err, "r.db.Find") + } + + return events, nil +} diff --git a/packages/eventindexer/repo/event_test.go b/packages/eventindexer/repo/event_test.go index 62b69010a9..60be679f2d 100644 --- a/packages/eventindexer/repo/event_test.go +++ b/packages/eventindexer/repo/event_test.go @@ -213,6 +213,60 @@ func TestIntegration_Event_GetCountByAddressAndEventName(t *testing.T) { } } +func TestIntegration_Event_GetByAddressAndEventName(t *testing.T) { + db, close, err := testMysql(t) + assert.Equal(t, nil, err) + + defer close() + + eventRepo, err := NewEventRepository(db) + assert.Equal(t, nil, err) + + _, err = eventRepo.Save(context.Background(), dummyProveEventOpts) + + assert.Equal(t, nil, err) + + _, err = eventRepo.Save(context.Background(), dummyProposeEventOpts) + + assert.Equal(t, nil, err) + + tests := []struct { + name string + address string + event string + wantLen int + wantErr error + }{ + { + "success", + dummyProposeEventOpts.Address, + dummyProposeEventOpts.Event, + 1, + nil, + }, + { + "none", + "0xfake", + dummyProposeEventOpts.Event, + 0, + nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resp, err := eventRepo.GetByAddressAndEventName( + context.Background(), + tt.address, + tt.event, + ) + spew.Dump(resp) + assert.Equal(t, tt.wantErr, err) + assert.Equal(t, tt.wantLen, len(resp)) + }) + } +} + func TestIntegration_Event_Delete(t *testing.T) { db, close, err := testMysql(t) assert.Equal(t, nil, err) From e92cdb8d54cf940872874698569a217408e9a2d5 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 20 Jun 2023 16:09:45 -0700 Subject: [PATCH 2/2] add pagination --- packages/eventindexer/event.go | 5 +- .../http/get_by_address_and_event.go | 12 ++--- .../http/get_by_address_and_event_test.go | 4 +- .../eventindexer/mock/event_repository.go | 9 +++- packages/eventindexer/repo/event.go | 22 +++++--- packages/eventindexer/repo/event_test.go | 54 ------------------- 6 files changed, 30 insertions(+), 76 deletions(-) diff --git a/packages/eventindexer/event.go b/packages/eventindexer/event.go index 15922fb212..b695fb9359 100644 --- a/packages/eventindexer/event.go +++ b/packages/eventindexer/event.go @@ -4,7 +4,9 @@ import ( "context" "database/sql" "math/big" + "net/http" + "github.com/morkid/paginate" "gorm.io/datatypes" ) @@ -67,7 +69,8 @@ type EventRepository interface { GetCountByAddressAndEventName(ctx context.Context, address string, event string) (int, error) GetByAddressAndEventName( ctx context.Context, + req *http.Request, address string, event string, - ) ([]*Event, error) + ) (paginate.Page, error) } diff --git a/packages/eventindexer/http/get_by_address_and_event.go b/packages/eventindexer/http/get_by_address_and_event.go index 7cf700edf3..38d1410f8b 100644 --- a/packages/eventindexer/http/get_by_address_and_event.go +++ b/packages/eventindexer/http/get_by_address_and_event.go @@ -5,16 +5,12 @@ import ( "github.com/cyberhorsey/webutils" "github.com/labstack/echo/v4" - "github.com/taikoxyz/taiko-mono/packages/eventindexer" ) -type GetByAddressAndEventNameResp struct { - Events []*eventindexer.Event `json:"events"` -} - func (srv *Server) GetByAddressAndEventName(c echo.Context) error { - events, err := srv.eventRepo.GetByAddressAndEventName( + page, err := srv.eventRepo.GetByAddressAndEventName( c.Request().Context(), + c.Request(), c.QueryParam("address"), c.QueryParam("event"), ) @@ -22,7 +18,5 @@ func (srv *Server) GetByAddressAndEventName(c echo.Context) error { return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, err) } - return c.JSON(http.StatusOK, &GetByAddressAndEventNameResp{ - Events: events, - }) + return c.JSON(http.StatusOK, page) } diff --git a/packages/eventindexer/http/get_by_address_and_event_test.go b/packages/eventindexer/http/get_by_address_and_event_test.go index 309307c1b2..526a3679d9 100644 --- a/packages/eventindexer/http/get_by_address_and_event_test.go +++ b/packages/eventindexer/http/get_by_address_and_event_test.go @@ -39,14 +39,14 @@ func Test_GetByAddressAndEvent(t *testing.T) { "0xhasntProposedAnything", eventindexer.EventNameBlockProposed, http.StatusOK, - []string{`{"events":`}, + []string{`{"items":`}, }, { "success", "0x123", eventindexer.EventNameBlockProposed, http.StatusOK, - []string{`{"events":`}, + []string{`{"items":`}, }, } diff --git a/packages/eventindexer/mock/event_repository.go b/packages/eventindexer/mock/event_repository.go index a3a1c6ea88..9b5e388213 100644 --- a/packages/eventindexer/mock/event_repository.go +++ b/packages/eventindexer/mock/event_repository.go @@ -3,7 +3,9 @@ package mock import ( "context" "math/rand" + "net/http" + "github.com/morkid/paginate" "github.com/taikoxyz/taiko-mono/packages/eventindexer" "gorm.io/datatypes" "gorm.io/gorm" @@ -61,9 +63,10 @@ func (r *EventRepository) GetCountByAddressAndEventName( func (r *EventRepository) GetByAddressAndEventName( ctx context.Context, + req *http.Request, address string, event string, -) ([]*eventindexer.Event, error) { +) (paginate.Page, error) { var events []*eventindexer.Event for _, e := range r.events { @@ -72,7 +75,9 @@ func (r *EventRepository) GetByAddressAndEventName( } } - return events, nil + return paginate.Page{ + Items: events, + }, nil } func (r *EventRepository) FindByEventTypeAndBlockID( diff --git a/packages/eventindexer/repo/event.go b/packages/eventindexer/repo/event.go index 5a51cb1dcf..da647870fb 100644 --- a/packages/eventindexer/repo/event.go +++ b/packages/eventindexer/repo/event.go @@ -2,7 +2,9 @@ package repo import ( "context" + "net/http" + "github.com/morkid/paginate" "github.com/pkg/errors" "github.com/taikoxyz/taiko-mono/packages/eventindexer" "gorm.io/datatypes" @@ -115,16 +117,20 @@ func (r *EventRepository) GetCountByAddressAndEventName( func (r *EventRepository) GetByAddressAndEventName( ctx context.Context, + req *http.Request, address string, event string, -) ([]*eventindexer.Event, error) { - var events []*eventindexer.Event +) (paginate.Page, error) { + pg := paginate.New(&paginate.Config{ + DefaultSize: 100, + }) - if err := r.db.GormDB(). - Raw("SELECT * FROM events WHERE event = ? AND address = ?", event, address). - Find(&events).Error; err != nil { - return nil, errors.Wrap(err, "r.db.Find") - } + q := r.db.GormDB(). + Raw("SELECT * FROM events WHERE event = ? AND address = ?", event, address) + + reqCtx := pg.With(q) + + page := reqCtx.Request(req).Response(&[]eventindexer.Event{}) - return events, nil + return page, nil } diff --git a/packages/eventindexer/repo/event_test.go b/packages/eventindexer/repo/event_test.go index 60be679f2d..62b69010a9 100644 --- a/packages/eventindexer/repo/event_test.go +++ b/packages/eventindexer/repo/event_test.go @@ -213,60 +213,6 @@ func TestIntegration_Event_GetCountByAddressAndEventName(t *testing.T) { } } -func TestIntegration_Event_GetByAddressAndEventName(t *testing.T) { - db, close, err := testMysql(t) - assert.Equal(t, nil, err) - - defer close() - - eventRepo, err := NewEventRepository(db) - assert.Equal(t, nil, err) - - _, err = eventRepo.Save(context.Background(), dummyProveEventOpts) - - assert.Equal(t, nil, err) - - _, err = eventRepo.Save(context.Background(), dummyProposeEventOpts) - - assert.Equal(t, nil, err) - - tests := []struct { - name string - address string - event string - wantLen int - wantErr error - }{ - { - "success", - dummyProposeEventOpts.Address, - dummyProposeEventOpts.Event, - 1, - nil, - }, - { - "none", - "0xfake", - dummyProposeEventOpts.Event, - 0, - nil, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - resp, err := eventRepo.GetByAddressAndEventName( - context.Background(), - tt.address, - tt.event, - ) - spew.Dump(resp) - assert.Equal(t, tt.wantErr, err) - assert.Equal(t, tt.wantLen, len(resp)) - }) - } -} - func TestIntegration_Event_Delete(t *testing.T) { db, close, err := testMysql(t) assert.Equal(t, nil, err)