From 8b753ee07eeee51adf48e72343b62abcde3b2338 Mon Sep 17 00:00:00 2001 From: jeff <113397187+cyberhorsey@users.noreply.github.com> Date: Tue, 14 Mar 2023 07:26:56 -0700 Subject: [PATCH] feat(relayer): add msgHash and event type lookups to findallbyaddress (#13310) Co-authored-by: shadab-taiko <108871478+shadab-taiko@users.noreply.github.com> --- packages/relayer/event.go | 14 +- .../relayer/http/get_events_by_address.go | 29 ++- packages/relayer/mock/event_repository.go | 41 +-- packages/relayer/repo/event.go | 40 ++- packages/relayer/repo/event_test.go | 242 +++++++++++------- 5 files changed, 202 insertions(+), 164 deletions(-) diff --git a/packages/relayer/event.go b/packages/relayer/event.go index e2e8e896e04..0038c5348fe 100644 --- a/packages/relayer/event.go +++ b/packages/relayer/event.go @@ -77,19 +77,21 @@ type SaveEventOpts struct { MessageOwner string } +type FindAllByAddressOpts struct { + Address common.Address + EventType *EventType + MsgHash *string + ChainID *big.Int +} + // EventRepository is used to interact with events in the store type EventRepository interface { Save(ctx context.Context, opts SaveEventOpts) (*Event, error) UpdateStatus(ctx context.Context, id int, status EventStatus) error - FindAllByAddressAndChainID( - ctx context.Context, - chainID *big.Int, - address common.Address, - ) ([]*Event, error) FindAllByAddress( ctx context.Context, req *http.Request, - address common.Address, + opts FindAllByAddressOpts, ) (paginate.Page, error) FindAllByMsgHash( ctx context.Context, diff --git a/packages/relayer/http/get_events_by_address.go b/packages/relayer/http/get_events_by_address.go index 62a6c7cdced..1596ed089c7 100644 --- a/packages/relayer/http/get_events_by_address.go +++ b/packages/relayer/http/get_events_by_address.go @@ -2,20 +2,47 @@ package http import ( "html" + "math/big" "net/http" + "strconv" "github.com/cyberhorsey/webutils" "github.com/ethereum/go-ethereum/common" "github.com/labstack/echo/v4" + "github.com/taikoxyz/taiko-mono/packages/relayer" ) func (srv *Server) GetEventsByAddress(c echo.Context) error { + chainID, _ := new(big.Int).SetString(c.QueryParam("chainID"), 10) + address := html.EscapeString(c.QueryParam("address")) + msgHash := html.EscapeString(c.QueryParam("msgHash")) + + eventTypeParam := html.EscapeString(c.QueryParam("eventType")) + + var eventType *relayer.EventType + + if eventTypeParam != "" { + i, err := strconv.Atoi(eventTypeParam) + if err != nil { + return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, err) + } + + et := relayer.EventType(i) + + eventType = &et + } + page, err := srv.eventRepo.FindAllByAddress( c.Request().Context(), c.Request(), - common.HexToAddress(address), + relayer.FindAllByAddressOpts{ + Address: common.HexToAddress(address), + MsgHash: &msgHash, + EventType: eventType, + ChainID: chainID, + }, ) if err != nil { return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, err) diff --git a/packages/relayer/mock/event_repository.go b/packages/relayer/mock/event_repository.go index 9846c33ae4a..5d4327708a9 100644 --- a/packages/relayer/mock/event_repository.go +++ b/packages/relayer/mock/event_repository.go @@ -3,11 +3,9 @@ package mock import ( "context" "encoding/json" - "math/big" "math/rand" "net/http" - "github.com/ethereum/go-ethereum/common" "github.com/morkid/paginate" "github.com/taikoxyz/taiko-mono/packages/relayer" "gorm.io/datatypes" @@ -61,45 +59,10 @@ func (r *EventRepository) UpdateStatus(ctx context.Context, id int, status relay return nil } -func (r *EventRepository) FindAllByAddressAndChainID( - ctx context.Context, - chainID *big.Int, - address common.Address, -) ([]*relayer.Event, error) { - type d struct { - Owner string `json:"Owner"` - } - - events := make([]*relayer.Event, 0) - - for _, e := range r.events { - if e.ChainID != int64(chainID.Uint64()) { - continue - } - - m, err := e.Data.MarshalJSON() - if err != nil { - return nil, err - } - - data := &d{} - if err := json.Unmarshal(m, data); err != nil { - return nil, err - } - - if data.Owner == address.Hex() { - events = append(events, e) - break - } - } - - return events, nil -} - func (r *EventRepository) FindAllByAddress( ctx context.Context, req *http.Request, - address common.Address, + opts relayer.FindAllByAddressOpts, ) (paginate.Page, error) { type d struct { Owner string `json:"Owner"` @@ -118,7 +81,7 @@ func (r *EventRepository) FindAllByAddress( return paginate.Page{}, err } - if data.Owner == address.Hex() { + if data.Owner == opts.Address.Hex() { events = append(events, e) break } diff --git a/packages/relayer/repo/event.go b/packages/relayer/repo/event.go index 97b5ae38ed9..9c1c10441e7 100644 --- a/packages/relayer/repo/event.go +++ b/packages/relayer/repo/event.go @@ -2,11 +2,10 @@ package repo import ( "context" - "math/big" - "net/http" "strings" - "github.com/ethereum/go-ethereum/common" + "net/http" + "github.com/morkid/paginate" "github.com/pkg/errors" "github.com/taikoxyz/taiko-mono/packages/relayer" @@ -42,6 +41,7 @@ func (r *EventRepository) Save(ctx context.Context, opts relayer.SaveEventOpts) MsgHash: opts.MsgHash, MessageOwner: opts.MessageOwner, } + if err := r.db.GormDB().Create(e).Error; err != nil { return nil, errors.Wrap(err, "r.db.Create") } @@ -79,35 +79,29 @@ func (r *EventRepository) FindAllByMsgHash( return e, nil } -func (r *EventRepository) FindAllByAddressAndChainID( - ctx context.Context, - chainID *big.Int, - address common.Address, -) ([]*relayer.Event, error) { - e := make([]*relayer.Event, 0) - // find all message sent events - if err := r.db.GormDB().Where("chain_id = ?", chainID.Int64()). - Where("message_owner = ?", strings.ToLower(address.Hex())). - Find(&e).Error; err != nil { - return nil, errors.Wrap(err, "r.db.Find") - } - - // find all message status changed events - - return e, nil -} - func (r *EventRepository) FindAllByAddress( ctx context.Context, req *http.Request, - address common.Address, + opts relayer.FindAllByAddressOpts, ) (paginate.Page, error) { pg := paginate.New(&paginate.Config{ DefaultSize: 100, }) q := r.db.GormDB(). - Model(&relayer.Event{}).Where("message_owner = ?", strings.ToLower(address.Hex())) + Model(&relayer.Event{}).Where("message_owner = ?", strings.ToLower(opts.Address.Hex())) + + if opts.EventType != nil { + q = q.Where("event_type = ?", *opts.EventType) + } + + if opts.MsgHash != nil && *opts.MsgHash != "" { + q = q.Where("msg_hash = ?", *opts.MsgHash) + } + + if opts.ChainID != nil { + q = q.Where("chain_id = ?", opts.ChainID.Int64()) + } reqCtx := pg.With(q) diff --git a/packages/relayer/repo/event_test.go b/packages/relayer/repo/event_test.go index 439bad5a3d9..f10cb20dfc0 100644 --- a/packages/relayer/repo/event_test.go +++ b/packages/relayer/repo/event_test.go @@ -16,6 +16,63 @@ import ( "gorm.io/datatypes" ) +var testMsgHash = "0x1" +var testSecondMsgHash = "0x2" +var testEventTypeSendETH = relayer.EventTypeSendETH +var testEventTypeSendERC20 = relayer.EventTypeSendERC20 +var addr = common.HexToAddress("0x71C7656EC7ab88b098defB751B7401B5f6d8976F") + +var testEvents = []relayer.Event{ + { + ID: 1, + Name: "name", + // nolint lll + Data: datatypes.JSON([]byte(fmt.Sprintf(`{"Message": {"Owner": "%s"}}`, strings.ToLower(addr.Hex())))), + ChainID: 1, + Status: relayer.EventStatusDone, + EventType: testEventTypeSendETH, + CanonicalTokenAddress: "0x1", + CanonicalTokenSymbol: "ETH", + CanonicalTokenName: "Ethereum", + CanonicalTokenDecimals: 18, + Amount: "1", + MsgHash: testMsgHash, + MessageOwner: addr.Hex(), + }, + { + ID: 2, + Name: "name", + // nolint lll + Data: datatypes.JSON([]byte(fmt.Sprintf(`{"Message": {"Owner": "%s"}}`, strings.ToLower(addr.Hex())))), + ChainID: 1, + Status: relayer.EventStatusDone, + EventType: testEventTypeSendERC20, + CanonicalTokenAddress: "0x1", + CanonicalTokenSymbol: "FAKE", + CanonicalTokenName: "Fake Token", + CanonicalTokenDecimals: 18, + Amount: "1", + MsgHash: testMsgHash, + MessageOwner: addr.Hex(), + }, + { + ID: 3, + Name: "name", + // nolint lll + Data: datatypes.JSON([]byte(fmt.Sprintf(`{"Message": {"Owner": "%s"}}`, strings.ToLower(addr.Hex())))), + ChainID: 1, + Status: relayer.EventStatusDone, + EventType: testEventTypeSendERC20, + CanonicalTokenAddress: "0x2", + CanonicalTokenSymbol: "FAKE", + CanonicalTokenName: "Fake Token", + CanonicalTokenDecimals: 18, + Amount: "1", + MsgHash: testSecondMsgHash, + MessageOwner: addr.Hex(), + }, +} + func Test_NewEventRepo(t *testing.T) { tests := []struct { name string @@ -137,7 +194,7 @@ func TestIntegration_Event_UpdateStatus(t *testing.T) { } } -func TestIntegration_Event_FindAllByAddressAndChainID(t *testing.T) { +func TestIntegration_Event_FindAllByAddress(t *testing.T) { db, close, err := testMysql(t) assert.Equal(t, nil, err) @@ -153,6 +210,7 @@ func TestIntegration_Event_FindAllByAddressAndChainID(t *testing.T) { Data: fmt.Sprintf(`{"Message": {"Owner": "%s"}}`, strings.ToLower(addr.Hex())), ChainID: big.NewInt(1), Status: relayer.EventStatusDone, + EventType: relayer.EventTypeSendETH, CanonicalTokenAddress: "0x1", CanonicalTokenSymbol: "ETH", CanonicalTokenName: "Ethereum", @@ -162,116 +220,110 @@ func TestIntegration_Event_FindAllByAddressAndChainID(t *testing.T) { MessageOwner: addr.Hex(), }) assert.Equal(t, nil, err) - tests := []struct { - name string - chainID *big.Int - address common.Address - wantResp []*relayer.Event - wantErr error - }{ - { - "success", - big.NewInt(1), - addr, - []*relayer.Event{ - { - ID: 1, - Name: "name", - // nolint lll - Data: datatypes.JSON([]byte(fmt.Sprintf(`{"Message": {"Owner": "%s"}}`, strings.ToLower(addr.Hex())))), - ChainID: 1, - Status: relayer.EventStatusDone, - EventType: relayer.EventTypeSendETH, - CanonicalTokenAddress: "0x1", - CanonicalTokenSymbol: "ETH", - CanonicalTokenName: "Ethereum", - CanonicalTokenDecimals: 18, - Amount: "1", - MsgHash: "0x1", - MessageOwner: addr.Hex(), - }, - }, - nil, - }, - { - "noneByChainID", - big.NewInt(2), - addr, - []*relayer.Event{}, - nil, - }, - { - "noneByAddr", - big.NewInt(1), - common.HexToAddress("0x165CD37b4C644C2921454429E7F9358d18A45e14"), - []*relayer.Event{}, - nil, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - resp, err := eventRepo.FindAllByAddressAndChainID(context.Background(), tt.chainID, tt.address) - assert.Equal(t, tt.wantResp, resp) - assert.Equal(t, tt.wantErr, err) - }) - } -} - -func TestIntegration_Event_FindAllByAddress(t *testing.T) { - db, close, err := testMysql(t) - assert.Equal(t, nil, err) - - defer close() - - eventRepo, err := NewEventRepository(db) - assert.Equal(t, nil, err) - - addr := common.HexToAddress("0x71C7656EC7ab88b098defB751B7401B5f6d8976F") _, err = eventRepo.Save(context.Background(), relayer.SaveEventOpts{ Name: "name", Data: fmt.Sprintf(`{"Message": {"Owner": "%s"}}`, strings.ToLower(addr.Hex())), ChainID: big.NewInt(1), Status: relayer.EventStatusDone, - EventType: relayer.EventTypeSendETH, + EventType: relayer.EventTypeSendERC20, CanonicalTokenAddress: "0x1", - CanonicalTokenSymbol: "ETH", - CanonicalTokenName: "Ethereum", + CanonicalTokenSymbol: "FAKE", + CanonicalTokenName: "Fake Token", CanonicalTokenDecimals: 18, Amount: "1", MsgHash: "0x1", MessageOwner: addr.Hex(), }) assert.Equal(t, nil, err) + + _, err = eventRepo.Save(context.Background(), relayer.SaveEventOpts{ + Name: "name", + Data: fmt.Sprintf(`{"Message": {"Owner": "%s"}}`, strings.ToLower(addr.Hex())), + ChainID: big.NewInt(1), + Status: relayer.EventStatusDone, + EventType: relayer.EventTypeSendERC20, + CanonicalTokenAddress: "0x2", + CanonicalTokenSymbol: "FAKE", + CanonicalTokenName: "Fake Token", + CanonicalTokenDecimals: 18, + Amount: "1", + MsgHash: "0x2", + MessageOwner: addr.Hex(), + }) + assert.Equal(t, nil, err) + tests := []struct { name string - address common.Address + opts relayer.FindAllByAddressOpts wantResp paginate.Page wantErr error }{ { - "success", - addr, + "successJustAddress", + relayer.FindAllByAddressOpts{ + Address: addr, + }, paginate.Page{ - Items: []relayer.Event{ - { - ID: 1, - Name: "name", - // nolint lll - Data: datatypes.JSON([]byte(fmt.Sprintf(`{"Message": {"Owner": "%s"}}`, strings.ToLower(addr.Hex())))), - ChainID: 1, - Status: relayer.EventStatusDone, - EventType: relayer.EventTypeSendETH, - CanonicalTokenAddress: "0x1", - CanonicalTokenSymbol: "ETH", - CanonicalTokenName: "Ethereum", - CanonicalTokenDecimals: 18, - Amount: "1", - MsgHash: "0x1", - MessageOwner: addr.Hex(), - }, - }, + Items: testEvents, + Page: 0, + Size: 100, + MaxPage: 1, + TotalPages: 1, + Total: 1, + Last: false, + First: true, + Visible: 1, + }, + nil, + }, + { + "successAddressAndMsgHash", + relayer.FindAllByAddressOpts{ + Address: addr, + MsgHash: &testMsgHash, + }, + paginate.Page{ + Items: testEvents[:2], + Page: 0, + Size: 100, + MaxPage: 1, + TotalPages: 1, + Total: 1, + Last: false, + First: true, + Visible: 1, + }, + nil, + }, + { + "successAddressAndEventType", + relayer.FindAllByAddressOpts{ + Address: addr, + EventType: &testEventTypeSendERC20, + }, + paginate.Page{ + Items: testEvents[1:3], + Page: 0, + Size: 100, + MaxPage: 1, + TotalPages: 1, + Total: 1, + Last: false, + First: true, + Visible: 1, + }, + nil, + }, + { + "successAddressMsgHashAndEventType", + relayer.FindAllByAddressOpts{ + Address: addr, + EventType: &testEventTypeSendERC20, + MsgHash: &testSecondMsgHash, + }, + paginate.Page{ + Items: testEvents[2:], Page: 0, Size: 100, MaxPage: 1, @@ -285,7 +337,9 @@ func TestIntegration_Event_FindAllByAddress(t *testing.T) { }, { "noneByAddr", - common.HexToAddress("0x165CD37b4C644C2921454429E7F9358d18A45e14"), + relayer.FindAllByAddressOpts{ + Address: common.HexToAddress("0x165CD37b4C644C2921454429E7F9358d18A45e14"), + }, paginate.Page{ Items: []relayer.Event{}, Page: 0, @@ -306,7 +360,7 @@ func TestIntegration_Event_FindAllByAddress(t *testing.T) { req, err := http.NewRequest(http.MethodGet, "/events", nil) assert.Equal(t, nil, err) - resp, err := eventRepo.FindAllByAddress(context.Background(), req, tt.address) + resp, err := eventRepo.FindAllByAddress(context.Background(), req, tt.opts) assert.Equal(t, tt.wantResp.Items, resp.Items) assert.Equal(t, tt.wantErr, err) }) @@ -322,8 +376,6 @@ func TestIntegration_Event_FindAllByMsgHash(t *testing.T) { eventRepo, err := NewEventRepository(db) assert.Equal(t, nil, err) - addr := common.HexToAddress("0x71C7656EC7ab88b098defB751B7401B5f6d8976F") - _, err = eventRepo.Save(context.Background(), relayer.SaveEventOpts{ Name: "name", Data: fmt.Sprintf(`{"Message": {"Owner": "%s"}}`, strings.ToLower(addr.Hex())),