From b37165662c076cf9ffb0984ffff73bfe8523b61a Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Mon, 14 Nov 2022 11:55:06 -0800 Subject: [PATCH 1/4] WIP on HTTP api for exposing events table for bridge UI --- go.mod | 20 ++++ go.sum | 53 ++++++++++ packages/relayer/.default.env | 3 +- packages/relayer/cli/cli.go | 30 ++++++ packages/relayer/errors.go | 9 +- packages/relayer/event.go | 7 +- packages/relayer/http/errors.go | 14 +++ .../relayer/http/get_events_by_address.go | 27 +++++ .../http/get_events_by_address_test.go | 68 +++++++++++++ packages/relayer/http/routes.go | 7 ++ packages/relayer/http/server.go | 98 +++++++++++++++++++ packages/relayer/http/server_test.go | 90 +++++++++++++++++ .../relayer/indexer/filter_then_subscribe.go | 2 +- packages/relayer/message/process_message.go | 2 +- packages/relayer/mock/event_repository.go | 90 +++++++++++++++++ packages/relayer/repo/event.go | 11 ++- packages/relayer/repo/event_test.go | 11 ++- 17 files changed, 525 insertions(+), 17 deletions(-) create mode 100644 packages/relayer/http/errors.go create mode 100644 packages/relayer/http/get_events_by_address.go create mode 100644 packages/relayer/http/get_events_by_address_test.go create mode 100644 packages/relayer/http/routes.go create mode 100644 packages/relayer/http/server.go create mode 100644 packages/relayer/http/server_test.go create mode 100644 packages/relayer/mock/event_repository.go diff --git a/go.mod b/go.mod index ff09077ea39..0b405828552 100644 --- a/go.mod +++ b/go.mod @@ -24,32 +24,48 @@ require ( github.com/Microsoft/go-winio v0.5.2 // indirect github.com/Microsoft/hcsshim v0.9.4 // indirect github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect + github.com/aymerick/douceur v0.2.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect + github.com/chris-ramon/douceur v0.2.0 // indirect github.com/containerd/cgroups v1.0.4 // indirect github.com/containerd/containerd v1.6.8 // indirect + github.com/cyberhorsey/webutils v0.0.0-20220929234343-770c4fa3beba // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set v1.8.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/docker v20.10.17+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/go-ole/go-ole v1.2.1 // indirect + github.com/go-playground/locales v0.13.0 // indirect + github.com/go-playground/universal-translator v0.17.0 // indirect + github.com/go-playground/validator/v10 v10.4.0 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/go-stack/stack v1.8.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/css v1.0.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + github.com/labstack/echo/v4 v4.9.1 // indirect + github.com/labstack/gommon v0.4.0 // indirect + github.com/leodido/go-urn v1.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/microcosm-cc/bluemonday v1.0.4 // indirect github.com/moby/sys/mount v0.3.3 // indirect github.com/moby/sys/mountinfo v0.6.2 // indirect github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect github.com/morikuni/aec v1.0.0 // indirect + github.com/neko-neko/echo-logrus/v2 v2.0.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect github.com/opencontainers/runc v1.1.3 // indirect @@ -59,10 +75,14 @@ require ( github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.1 // indirect go.opencensus.io v0.23.0 // indirect golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad // indirect google.golang.org/grpc v1.47.0 // indirect google.golang.org/protobuf v1.28.0 // indirect diff --git a/go.sum b/go.sum index cedf6ecb41c..1f6004e0914 100644 --- a/go.sum +++ b/go.sum @@ -84,6 +84,8 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -114,6 +116,8 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cb github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= +github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU= +github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -248,6 +252,8 @@ github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberhorsey/errors v0.0.0-20220929234051-087d6d8bb841 h1:FaPua89k9KmkkiptlTAmYzcTsn1IFdQsqneuFO6IAu8= github.com/cyberhorsey/errors v0.0.0-20220929234051-087d6d8bb841/go.mod h1:qSH/IvpdArCjfny4ODMko/7U0z4JoNIWctgCnUrapnI= +github.com/cyberhorsey/webutils v0.0.0-20220929234343-770c4fa3beba h1:bNdCrXULXOZo7PLF+Y7u5njDCHr0jgLEKgLsLCFZtck= +github.com/cyberhorsey/webutils v0.0.0-20220929234343-770c4fa3beba/go.mod h1:SsnedeS2nEcRNpaMO2cQ+0jv86D++V7oMPhF5lKxOwo= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= @@ -267,6 +273,7 @@ github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfz github.com/denisenkom/go-mssqldb v0.12.2 h1:1OcPn5GBIobjWNd+8yjfHNIaFX14B1pWI3F9HZy5KXw= github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= @@ -346,6 +353,13 @@ github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8 github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.4.0 h1:72qIR/m8ybvL8L5TIyfgrigqkrw7kVYAvjEvpT85l70= +github.com/go-playground/validator/v10 v10.4.0/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -367,6 +381,8 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= @@ -441,6 +457,8 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= @@ -563,6 +581,16 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/labstack/echo/v4 v4.0.0/go.mod h1:tZv7nai5buKSg5h/8E6zz4LsD/Dqh9/91Mvs7Z5Zyno= +github.com/labstack/echo/v4 v4.1.15/go.mod h1:GWO5IBVzI371K8XJe50CSvHjQCafK6cw8R/moLhEU6o= +github.com/labstack/echo/v4 v4.9.1 h1:GliPYSpzGKlyOhqIbG8nmHBo3i1saKWFOgh41AN3b+Y= +github.com/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo= +github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4= +github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= +github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= +github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -578,13 +606,19 @@ github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7 github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= @@ -595,6 +629,8 @@ github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg= +github.com/microcosm-cc/bluemonday v1.0.4/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -627,6 +663,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/neko-neko/echo-logrus/v2 v2.0.1 h1:BX2U6uv2N3UiUY75y+SntQak5S1AJIel9j+5Y6h4Nb4= +github.com/neko-neko/echo-logrus/v2 v2.0.1/go.mod h1:GDYWo9CY4VXk/vn5ac5reoutYEkZEexlFI01MzHXVG0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -747,6 +785,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -810,6 +849,13 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= @@ -858,6 +904,7 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -866,6 +913,7 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -975,6 +1023,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1044,8 +1093,11 @@ golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1071,6 +1123,7 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/packages/relayer/.default.env b/packages/relayer/.default.env index 3af94987915..f78ba463211 100644 --- a/packages/relayer/.default.env +++ b/packages/relayer/.default.env @@ -7,4 +7,5 @@ RELAYER_ECDSA_KEY= L1_BRIDGE_ADDRESS=0xa566811E9E63e4F573Df89d5453bB89F239F7e10 L2_BRIDGE_ADDRESS=0xa566811E9E63e4F573Df89d5453bB89F239F7e10 L1_RPC_URL="wss://eth-goerli.g.alchemy.com/v2/bPAA5rQ42Zoo4ts9TYnTB2t0cuc5lf7_" -L2_RPC_URL="wss://rinkeby-light.eth.linkpool.io/ws" \ No newline at end of file +L2_RPC_URL="wss://rinkeby-light.eth.linkpool.io/ws" +CORS_ORIGINS=* \ No newline at end of file diff --git a/packages/relayer/cli/cli.go b/packages/relayer/cli/cli.go index bd464e9acf7..a11d69ab26d 100644 --- a/packages/relayer/cli/cli.go +++ b/packages/relayer/cli/cli.go @@ -4,15 +4,18 @@ import ( "context" "fmt" "os" + "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rpc" + "github.com/labstack/echo/v4" "github.com/ethereum/go-ethereum/ethclient" "github.com/joho/godotenv" "github.com/pkg/errors" log "github.com/sirupsen/logrus" "github.com/taikochain/taiko-mono/packages/relayer" + "github.com/taikochain/taiko-mono/packages/relayer/http" "github.com/taikochain/taiko-mono/packages/relayer/indexer" "github.com/taikochain/taiko-mono/packages/relayer/repo" "gorm.io/driver/mysql" @@ -55,6 +58,15 @@ func Run(mode Mode, layer Layer) { log.Fatal(err) } + srv, err := newHTTPServer(db) + if err != nil { + log.Fatal(err) + } + + go func() { + srv.Start(fmt.Sprintf(":%v", os.Getenv("HTTP_PORT"))) + }() + indexers, closeFunc, err := makeIndexers(layer, db) if err != nil { sqlDB.Close() @@ -209,3 +221,21 @@ func loadAndValidateEnv() error { return errors.Errorf("Missing env vars: %v", missing) } + +func newHTTPServer(db *gorm.DB) (*http.Server, error) { + eventRepo, err := repo.NewEventRepository(db) + if err != nil { + return nil, err + } + + srv, err := http.NewServer(http.NewServerOpts{ + EventRepo: eventRepo, + Echo: echo.New(), + CorsOrigins: strings.Split(os.Getenv("CORS_ORIGINS"), ","), + }) + if err != nil { + return nil, err + } + + return srv, nil +} diff --git a/packages/relayer/errors.go b/packages/relayer/errors.go index db47dd73295..415796059f8 100644 --- a/packages/relayer/errors.go +++ b/packages/relayer/errors.go @@ -11,8 +11,9 @@ var ( "ERR_NO_BLOCK_REPOSITORY", "BlockRepository is required", ) - ErrNoProver = errors.Validation.NewWithKeyAndDetail("ERR_NO_PROVER", "Prover is required") - ErrNoRPCClient = errors.Validation.NewWithKeyAndDetail("ERR_NO_RPC_CLIENT", "RPCClient is required") - ErrNoBridge = errors.Validation.NewWithKeyAndDetail("ERR_NO_BRIDGE", "Bridge is required") - ErrNoTaikoL2 = errors.Validation.NewWithKeyAndDetail("ERR_NO_TAIKO_L2", "TaikoL2 is required") + ErrNoProver = errors.Validation.NewWithKeyAndDetail("ERR_NO_PROVER", "Prover is required") + ErrNoRPCClient = errors.Validation.NewWithKeyAndDetail("ERR_NO_RPC_CLIENT", "RPCClient is required") + ErrNoBridge = errors.Validation.NewWithKeyAndDetail("ERR_NO_BRIDGE", "Bridge is required") + ErrNoTaikoL2 = errors.Validation.NewWithKeyAndDetail("ERR_NO_TAIKO_L2", "TaikoL2 is required") + ErrNoCORSOrigins = errors.Validation.NewWithKeyAndDetail("ERR_NO_CORS_ORIGINS", "CORS Origins are required") ) diff --git a/packages/relayer/event.go b/packages/relayer/event.go index bf27aabf5f6..374a679ee94 100644 --- a/packages/relayer/event.go +++ b/packages/relayer/event.go @@ -1,8 +1,10 @@ package relayer import ( + "context" "math/big" + "github.com/ethereum/go-ethereum/common" "gorm.io/datatypes" ) @@ -47,6 +49,7 @@ type SaveEventOpts struct { // EventRepository is used to interact with events in the store type EventRepository interface { - Save(opts SaveEventOpts) (*Event, error) - UpdateStatus(id int, status EventStatus) error + Save(ctx context.Context, opts SaveEventOpts) (*Event, error) + UpdateStatus(ctx context.Context, id int, status EventStatus) error + FindAllByAddress(ctx context.Context, chainID *big.Int, address common.Address) ([]*Event, error) } diff --git a/packages/relayer/http/errors.go b/packages/relayer/http/errors.go new file mode 100644 index 00000000000..438fea9c9d9 --- /dev/null +++ b/packages/relayer/http/errors.go @@ -0,0 +1,14 @@ +package http + +import "github.com/cyberhorsey/errors" + +var ( + ErrNoHTTPFramework = errors.Validation.NewWithKeyAndDetail( + "ERR_NO_HTTP_ENGINE", + "HTTP framework required", + ) + ErrNoRewarder = errors.Validation.NewWithKeyAndDetail( + "ERR_NO_REWARDER", + "Rewarder is required", + ) +) diff --git a/packages/relayer/http/get_events_by_address.go b/packages/relayer/http/get_events_by_address.go new file mode 100644 index 00000000000..8f4b5c3cbf4 --- /dev/null +++ b/packages/relayer/http/get_events_by_address.go @@ -0,0 +1,27 @@ +package http + +import ( + "errors" + "math/big" + "net/http" + + "github.com/cyberhorsey/webutils" + "github.com/ethereum/go-ethereum/common" + "github.com/labstack/echo/v4" +) + +func (srv *Server) GetEventsByAddress(c echo.Context) error { + chainID, ok := new(big.Int).SetString(c.QueryParam("chainID"), 10) + if !ok { + return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, errors.New("invalid chain id")) + } + + address := c.QueryParam("address") + + events, err := srv.eventRepo.FindAllByAddress(c.Request().Context(), chainID, common.HexToAddress(address)) + if err != nil { + return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, err) + } + + return c.JSON(http.StatusOK, events) +} diff --git a/packages/relayer/http/get_events_by_address_test.go b/packages/relayer/http/get_events_by_address_test.go new file mode 100644 index 00000000000..3001185c142 --- /dev/null +++ b/packages/relayer/http/get_events_by_address_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/taikochain/taiko-mono/packages/relayer" +) + +func Test_GetEventsByAddress(t *testing.T) { + srv := newTestServer("") + + srv.eventRepo.Save(context.Background(), relayer.SaveEventOpts{ + Name: "name", + Data: `{"Owner": "0x0000000000000000000000000000000000000123"}`, + ChainID: big.NewInt(167001), + Status: relayer.EventStatusNew, + }) + + tests := []struct { + name string + address string + chainID string + wantStatus int + wantBodyRegexpMatches []string + }{ + { + "successEmptyList", + "0x456", + "167001", + http.StatusOK, + []string{`\[\]`}, + }, + { + "success", + "0x0000000000000000000000000000000000000123", + "167001", + http.StatusOK, + []string{`[{"id":780800018316137516,"name":"name", + "data":{"Owner":"0x0000000000000000000000000000000000000123"},"status":0,"chainID":167001}]`}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + req := testutils.NewUnauthenticatedRequest( + echo.GET, + fmt.Sprintf("/events?address=%v&chainID=%v", + tt.address, + tt.chainID), + + nil, + ) + + rec := httptest.NewRecorder() + + srv.ServeHTTP(rec, req) + + testutils.AssertStatusAndBody(t, rec, tt.wantStatus, tt.wantBodyRegexpMatches) + }) + } +} diff --git a/packages/relayer/http/routes.go b/packages/relayer/http/routes.go new file mode 100644 index 00000000000..45ad580b75b --- /dev/null +++ b/packages/relayer/http/routes.go @@ -0,0 +1,7 @@ +package http + +func (srv *Server) configureRoutes() { + srv.echo.GET("/health", srv.Health) + + srv.echo.GET("/events", srv.GetEventsByAddress) +} diff --git a/packages/relayer/http/server.go b/packages/relayer/http/server.go new file mode 100644 index 00000000000..74e30192332 --- /dev/null +++ b/packages/relayer/http/server.go @@ -0,0 +1,98 @@ +package http + +import ( + "context" + "net/http" + "os" + + "github.com/labstack/echo/v4/middleware" + "github.com/taikochain/taiko-mono/packages/relayer" + + echo "github.com/labstack/echo/v4" +) + +type Server struct { + echo *echo.Echo + eventRepo relayer.EventRepository +} + +type NewServerOpts struct { + Echo *echo.Echo + EventRepo relayer.EventRepository + CorsOrigins []string +} + +func (opts NewServerOpts) Validate() error { + if opts.Echo == nil { + return ErrNoHTTPFramework + } + + if opts.EventRepo == nil { + return relayer.ErrNoEventRepository + } + + if opts.CorsOrigins == nil { + return relayer.ErrNoCORSOrigins + } + + return nil +} + +func NewServer(opts NewServerOpts) (*Server, error) { + if err := opts.Validate(); err != nil { + return nil, err + } + + srv := &Server{ + echo: opts.Echo, + eventRepo: opts.EventRepo, + } + + srv.configureRoutes() + srv.configureMiddleware(opts.CorsOrigins) + + return srv, nil +} + +// Start starts the HTTP server +func (srv *Server) Start(address string) error { + return srv.echo.Start(address) +} + +// Shutdown shuts down the HTTP server +func (srv *Server) Shutdown(ctx context.Context) error { + return srv.echo.Shutdown(ctx) +} + +// ServeHTTP implements the `http.Handler` interface which serves HTTP requests +func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { + srv.echo.ServeHTTP(w, r) +} + +// Health endpoints for probes +func (srv *Server) Health(c echo.Context) error { + return c.NoContent(http.StatusOK) +} + +func LogSkipper(c echo.Context) bool { + return c.Request().URL.Path == "/health" +} + +func (srv *Server) configureMiddleware(corsOrigins []string) { + srv.echo.Use(middleware.RequestID()) + + srv.echo.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ + Skipper: LogSkipper, + Format: `{"time":"${time_rfc3339_nano}","level":"INFO","message":{"id":"${id}","remote_ip":"${remote_ip}",` + //nolint:lll + `"host":"${host}","method":"${method}","uri":"${uri}","user_agent":"${user_agent}",` + //nolint:lll + `"response_status":${status},"error":"${error}","latency":${latency},"latency_human":"${latency_human}",` + + `"bytes_in":${bytes_in},"bytes_out":${bytes_out}}}` + "\n", + Output: os.Stdout, + })) + + srv.echo.Use(middleware.CORSWithConfig(middleware.CORSConfig{ + AllowOrigins: corsOrigins, + AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept}, + AllowMethods: []string{http.MethodGet, http.MethodHead}, + })) +} diff --git a/packages/relayer/http/server_test.go b/packages/relayer/http/server_test.go new file mode 100644 index 00000000000..c195d70c01c --- /dev/null +++ b/packages/relayer/http/server_test.go @@ -0,0 +1,90 @@ +package http + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/joho/godotenv" + echo "github.com/labstack/echo/v4" + "github.com/stretchr/testify/assert" + "github.com/taikochain/taiko-mono/packages/relayer" + "github.com/taikochain/taiko-mono/packages/relayer/mock" + "github.com/taikochain/taiko-mono/packages/relayer/repo" +) + +var includeTokens = []string{"1INCH"} + +func newTestServer(url string) *Server { + _ = godotenv.Load("../.test.env") + + srv := &Server{ + echo: echo.New(), + eventRepo: mock.NewEventRepository(), + } + srv.configureRoutes() + + return srv +} + +func Test_NewServer(t *testing.T) { + tests := []struct { + name string + opts NewServerOpts + wantErr error + }{ + { + "success", + NewServerOpts{ + Echo: echo.New(), + EventRepo: &repo.EventRepository{}, + CorsOrigins: make([]string, 0), + }, + nil, + }, + { + "noEventRepo", + NewServerOpts{ + Echo: echo.New(), + CorsOrigins: make([]string, 0), + }, + relayer.ErrNoEventRepository, + }, + { + "noHttpFramework", + NewServerOpts{ + EventRepo: &repo.EventRepository{}, + CorsOrigins: make([]string, 0), + }, + ErrNoHTTPFramework, + }, + } + + for _, tt := range tests { + _, err := NewServer(tt.opts) + assert.Equal(t, tt.wantErr, err) + } +} + +func Test_Health(t *testing.T) { + srv := newTestServer("") + + req, _ := http.NewRequest(echo.GET, "/health", nil) + rec := httptest.NewRecorder() + + srv.ServeHTTP(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("Test_Health expected code %v, got %v", http.StatusOK, rec.Code) + } +} + +func Test_StartShutdown(t *testing.T) { + srv := newTestServer("") + + go func() { + _ = srv.Start(":3928") + }() + assert.Nil(t, srv.Shutdown(context.Background())) +} diff --git a/packages/relayer/indexer/filter_then_subscribe.go b/packages/relayer/indexer/filter_then_subscribe.go index 675bda481d4..a2527514aa0 100644 --- a/packages/relayer/indexer/filter_then_subscribe.go +++ b/packages/relayer/indexer/filter_then_subscribe.go @@ -173,7 +173,7 @@ func (svc *Service) handleEvent(ctx context.Context, chainID *big.Int, event *co eventStatus = relayer.EventStatusNewOnlyOwner } - e, err := svc.eventRepo.Save(relayer.SaveEventOpts{ + e, err := svc.eventRepo.Save(ctx, relayer.SaveEventOpts{ Name: eventName, Data: string(marshaled), ChainID: chainID, diff --git a/packages/relayer/message/process_message.go b/packages/relayer/message/process_message.go index 5b895258b6d..21f77ffe21d 100644 --- a/packages/relayer/message/process_message.go +++ b/packages/relayer/message/process_message.go @@ -110,7 +110,7 @@ func (p *Processor) ProcessMessage( log.Infof("updating message status to: %v", relayer.EventStatus(messageStatus).String()) // update message status - if err := p.eventRepo.UpdateStatus(e.ID, relayer.EventStatus(messageStatus)); err != nil { + if err := p.eventRepo.UpdateStatus(ctx, e.ID, relayer.EventStatus(messageStatus)); err != nil { return errors.Wrap(err, "s.eventRepo.UpdateStatus") } diff --git a/packages/relayer/mock/event_repository.go b/packages/relayer/mock/event_repository.go new file mode 100644 index 00000000000..5a97fa242f4 --- /dev/null +++ b/packages/relayer/mock/event_repository.go @@ -0,0 +1,90 @@ +package mock + +import ( + "context" + "encoding/json" + "errors" + "math/big" + "math/rand" + + "github.com/ethereum/go-ethereum/common" + "github.com/taikochain/taiko-mono/packages/relayer" + "gorm.io/datatypes" +) + +type EventRepository struct { + events []*relayer.Event +} + +func NewEventRepository() *EventRepository { + return &EventRepository{ + events: make([]*relayer.Event, 0), + } +} +func (r *EventRepository) Save(ctx context.Context, opts relayer.SaveEventOpts) (*relayer.Event, error) { + r.events = append(r.events, &relayer.Event{ + ID: rand.Int(), // nolint: gosec + Data: datatypes.JSON(opts.Data), + Status: opts.Status, + ChainID: opts.ChainID.Int64(), + Name: opts.Name, + }) + + return nil, nil +} + +func (r *EventRepository) UpdateStatus(ctx context.Context, id int, status relayer.EventStatus) error { + var event *relayer.Event + + var index int + + for i, e := range r.events { + if e.ID == id { + event = e + index = i + + break + } + } + + if event == nil { + return errors.New("id not found") + } + + event.Status = status + + r.events[index] = event + + return nil +} + +func (r *EventRepository) FindAllByAddress( + 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 { + 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 +} diff --git a/packages/relayer/repo/event.go b/packages/relayer/repo/event.go index 0f598319c74..7b6709db94a 100644 --- a/packages/relayer/repo/event.go +++ b/packages/relayer/repo/event.go @@ -1,6 +1,7 @@ package repo import ( + "context" "math/big" "github.com/ethereum/go-ethereum/common" @@ -24,7 +25,7 @@ func NewEventRepository(db *gorm.DB) (*EventRepository, error) { }, nil } -func (r *EventRepository) Save(opts relayer.SaveEventOpts) (*relayer.Event, error) { +func (r *EventRepository) Save(ctx context.Context, opts relayer.SaveEventOpts) (*relayer.Event, error) { e := &relayer.Event{ Data: datatypes.JSON(opts.Data), Status: opts.Status, @@ -38,7 +39,7 @@ func (r *EventRepository) Save(opts relayer.SaveEventOpts) (*relayer.Event, erro return e, nil } -func (r *EventRepository) UpdateStatus(id int, status relayer.EventStatus) error { +func (r *EventRepository) UpdateStatus(ctx context.Context, id int, status relayer.EventStatus) error { e := &relayer.Event{} if err := r.db.Where("id = ?", id).First(e).Error; err != nil { return errors.Wrap(err, "r.db.First") @@ -52,7 +53,11 @@ func (r *EventRepository) UpdateStatus(id int, status relayer.EventStatus) error return nil } -func (r *EventRepository) FindAllByAddress(chainID *big.Int, address common.Address) ([]*relayer.Event, error) { +func (r *EventRepository) FindAllByAddress( + ctx context.Context, + chainID *big.Int, + address common.Address, +) ([]*relayer.Event, error) { e := make([]*relayer.Event, 0) if err := r.db.Where("chain_id = ?", chainID.Int64()). Find(&e, datatypes.JSONQuery("data"). diff --git a/packages/relayer/repo/event_test.go b/packages/relayer/repo/event_test.go index b31b1fcd54a..47dad3b672a 100644 --- a/packages/relayer/repo/event_test.go +++ b/packages/relayer/repo/event_test.go @@ -1,6 +1,7 @@ package repo import ( + "context" "fmt" "math/big" "testing" @@ -64,7 +65,7 @@ func TestIntegration_Event_Save(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - _, err = eventRepo.Save(tt.opts) + _, err = eventRepo.Save(context.Background(), tt.opts) assert.Equal(t, tt.wantErr, err) }) } @@ -102,7 +103,7 @@ func TestIntegration_Event_UpdateStatus(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if tt.name == "success" { - _, err := eventRepo.Save( + _, err := eventRepo.Save(context.Background(), relayer.SaveEventOpts{ Name: "test", ChainID: big.NewInt(1), @@ -111,7 +112,7 @@ func TestIntegration_Event_UpdateStatus(t *testing.T) { ) assert.Equal(t, nil, err) } - err := eventRepo.UpdateStatus(tt.id, tt.status) + err := eventRepo.UpdateStatus(context.Background(), tt.id, tt.status) assert.Equal(t, tt.wantErr, err != nil) }) } @@ -128,7 +129,7 @@ func TestIntegration_Event_FindAllByAddress(t *testing.T) { addr := common.HexToAddress("0x71C7656EC7ab88b098defB751B7401B5f6d8976F") - _, err = eventRepo.Save(relayer.SaveEventOpts{ + _, err = eventRepo.Save(context.Background(), relayer.SaveEventOpts{ Name: "name", Data: fmt.Sprintf(`{"Owner":"%s"}`, addr.Hex()), ChainID: big.NewInt(1), @@ -175,7 +176,7 @@ func TestIntegration_Event_FindAllByAddress(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - resp, err := eventRepo.FindAllByAddress(tt.chainID, tt.address) + resp, err := eventRepo.FindAllByAddress(context.Background(), tt.chainID, tt.address) assert.Equal(t, tt.wantResp, resp) assert.Equal(t, tt.wantErr, err) }) From 0b27563cae9ec9993380bae1b40bf745402408a7 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Mon, 14 Nov 2022 12:12:12 -0800 Subject: [PATCH 2/4] error checking --- packages/relayer/cli/cli.go | 4 +++- packages/relayer/http/get_events_by_address_test.go | 5 ++++- packages/relayer/http/server_test.go | 2 -- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/relayer/cli/cli.go b/packages/relayer/cli/cli.go index a11d69ab26d..2184121f610 100644 --- a/packages/relayer/cli/cli.go +++ b/packages/relayer/cli/cli.go @@ -64,7 +64,9 @@ func Run(mode Mode, layer Layer) { } go func() { - srv.Start(fmt.Sprintf(":%v", os.Getenv("HTTP_PORT"))) + if err := srv.Start(fmt.Sprintf(":%v", os.Getenv("HTTP_PORT"))); err != nil { + log.Fatal(err) + } }() indexers, closeFunc, err := makeIndexers(layer, db) diff --git a/packages/relayer/http/get_events_by_address_test.go b/packages/relayer/http/get_events_by_address_test.go index 3001185c142..4c661965a47 100644 --- a/packages/relayer/http/get_events_by_address_test.go +++ b/packages/relayer/http/get_events_by_address_test.go @@ -10,19 +10,22 @@ import ( "github.com/cyberhorsey/webutils/testutils" "github.com/labstack/echo/v4" + "github.com/stretchr/testify/assert" "github.com/taikochain/taiko-mono/packages/relayer" ) func Test_GetEventsByAddress(t *testing.T) { srv := newTestServer("") - srv.eventRepo.Save(context.Background(), relayer.SaveEventOpts{ + _, err := srv.eventRepo.Save(context.Background(), relayer.SaveEventOpts{ Name: "name", Data: `{"Owner": "0x0000000000000000000000000000000000000123"}`, ChainID: big.NewInt(167001), Status: relayer.EventStatusNew, }) + assert.Equal(t, nil, err) + tests := []struct { name string address string diff --git a/packages/relayer/http/server_test.go b/packages/relayer/http/server_test.go index c195d70c01c..7ade82ff7c1 100644 --- a/packages/relayer/http/server_test.go +++ b/packages/relayer/http/server_test.go @@ -14,8 +14,6 @@ import ( "github.com/taikochain/taiko-mono/packages/relayer/repo" ) -var includeTokens = []string{"1INCH"} - func newTestServer(url string) *Server { _ = godotenv.Load("../.test.env") From 898e4eb4f0fa734d2bd5160ef3f40287e35036b4 Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 22 Nov 2022 18:05:09 -0800 Subject: [PATCH 3/4] escape string --- packages/relayer/http/get_events_by_address.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/relayer/http/get_events_by_address.go b/packages/relayer/http/get_events_by_address.go index 8f4b5c3cbf4..580793e910b 100644 --- a/packages/relayer/http/get_events_by_address.go +++ b/packages/relayer/http/get_events_by_address.go @@ -2,6 +2,7 @@ package http import ( "errors" + "html" "math/big" "net/http" @@ -16,7 +17,7 @@ func (srv *Server) GetEventsByAddress(c echo.Context) error { return webutils.LogAndRenderErrors(c, http.StatusUnprocessableEntity, errors.New("invalid chain id")) } - address := c.QueryParam("address") + address := html.EscapeString(c.QueryParam("address")) events, err := srv.eventRepo.FindAllByAddress(c.Request().Context(), chainID, common.HexToAddress(address)) if err != nil { From 18966fc2c5454cab604ceeac0bd611960fbb24aa Mon Sep 17 00:00:00 2001 From: Jeffery Walsh Date: Tue, 22 Nov 2022 18:14:09 -0800 Subject: [PATCH 4/4] newHTTPServer tests --- packages/relayer/cli/cli_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/relayer/cli/cli_test.go b/packages/relayer/cli/cli_test.go index c6b0f919d26..1f762cee220 100644 --- a/packages/relayer/cli/cli_test.go +++ b/packages/relayer/cli/cli_test.go @@ -217,3 +217,21 @@ func Test_makeIndexers(t *testing.T) { }) } } + +func Test_newHTTPServer(t *testing.T) { + db, cancel, err := testMysql(t) + if err != nil { + t.Fatal(err) + } + + defer cancel() + + srv, err := newHTTPServer(db) + assert.Nil(t, err) + assert.NotNil(t, srv) +} + +func Test_newHTTPServer_nilDB(t *testing.T) { + _, err := newHTTPServer(nil) + assert.NotNil(t, err) +}