Feature/refactor api (#34)
* Refactor error handling and comments * Refactor and improve error handling and logs
This commit is contained in:
parent
d7e2cd55fe
commit
8ed4804d63
|
@ -1,9 +0,0 @@
|
|||
package api
|
||||
|
||||
// API codes used in guardian node.
|
||||
// The same codes are used to facilitate portability to the new api.
|
||||
const (
|
||||
InvalidArgument = 3
|
||||
NotFound = 5
|
||||
Internal = 13
|
||||
)
|
|
@ -1,12 +0,0 @@
|
|||
package errors
|
||||
|
||||
import "errors"
|
||||
|
||||
func IsOf(received error, targets ...error) bool {
|
||||
for _, t := range targets {
|
||||
if errors.Is(received, t) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
|
@ -3,27 +3,26 @@ module github.com/wormhole-foundation/wormhole-explorer/api
|
|||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/ansrivas/fiberprometheus/v2 v2.4.1
|
||||
github.com/certusone/wormhole/node v0.0.0-20220907133901-8e231501b6cd
|
||||
github.com/gofiber/fiber/v2 v2.39.0
|
||||
github.com/ipfs/go-log/v2 v2.5.1
|
||||
github.com/spf13/viper v1.13.0
|
||||
go.mongodb.org/mongo-driver v1.10.3
|
||||
go.uber.org/zap v1.22.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/ansrivas/fiberprometheus/v2 v2.4.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/btcsuite/btcd v0.22.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/ethereum/go-ethereum v1.10.6 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/gofiber/adaptor/v2 v2.1.29 // indirect
|
||||
github.com/gogo/protobuf v1.3.3 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.3 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/ipfs/go-log v1.0.5 // indirect
|
||||
github.com/ipfs/go-log/v2 v2.5.1 // indirect
|
||||
github.com/klauspost/compress v1.15.12 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
|
@ -32,7 +31,6 @@ require (
|
|||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
|
@ -55,7 +53,6 @@ require (
|
|||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.8.0 // indirect
|
||||
go.uber.org/zap v1.22.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
|
|
22
api/go.sum
22
api/go.sum
|
@ -83,6 +83,7 @@ github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbE
|
|||
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM=
|
||||
github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||
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=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
|
@ -105,7 +106,6 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA
|
|||
github.com/certusone/wormhole/node v0.0.0-20220907133901-8e231501b6cd h1:j/D2a0Hvs+JBKteCTFGhi9f7MA0SaDE+BPFoGNqSENo=
|
||||
github.com/certusone/wormhole/node v0.0.0-20220907133901-8e231501b6cd/go.mod h1:hbEdpBxPoBplIJ+PMVitVGX5194g+Opd7dvONcxhykQ=
|
||||
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
|
@ -173,8 +173,6 @@ github.com/gofiber/adaptor/v2 v2.1.25/go.mod h1:gOxtwMVqUStB5goAYtKd+hSvGupdd+aR
|
|||
github.com/gofiber/adaptor/v2 v2.1.29 h1:JnYd6fbqVM9D4zPchk+kg89PfxyuKqZKhBWGQDHfKH4=
|
||||
github.com/gofiber/adaptor/v2 v2.1.29/go.mod h1:z4mAV9mMsUgIEVGGS5Ii6ZMTJq4VdV1KWL1JAbsZdUA=
|
||||
github.com/gofiber/fiber/v2 v2.36.0/go.mod h1:tgCr+lierLwLoVHHO/jn3Niannv34WRkQETU8wiL9fQ=
|
||||
github.com/gofiber/fiber/v2 v2.38.1 h1:GEQ/Yt3Wsf2a30iTqtLXlBYJZso0JXPovt/tmj5H9jU=
|
||||
github.com/gofiber/fiber/v2 v2.38.1/go.mod h1:t0NlbaXzuGH7I+7M4paE848fNWInZ7mfxI/Er1fTth8=
|
||||
github.com/gofiber/fiber/v2 v2.39.0 h1:uhWpYQ6EHN8J7FOPYbI2hrdBD/KNZBC5CjbuOd4QUt4=
|
||||
github.com/gofiber/fiber/v2 v2.39.0/go.mod h1:Cmuu+elPYGqlvQvdKyjtYsjGMi69PDp8a1AY2I5B2gM=
|
||||
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
|
@ -271,9 +269,6 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y
|
|||
github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE=
|
||||
github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0=
|
||||
github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po=
|
||||
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
|
||||
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
|
||||
github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
|
||||
github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
|
||||
github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
|
@ -302,8 +297,6 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6
|
|||
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A=
|
||||
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM=
|
||||
github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||
|
@ -371,8 +364,6 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
|||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
|
||||
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
|
||||
github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
|
@ -420,7 +411,6 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
|
|||
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
|
||||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4=
|
||||
github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI=
|
||||
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
|
@ -482,7 +472,6 @@ github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/X
|
|||
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/fasthttp v1.38.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
|
||||
github.com/valyala/fasthttp v1.40.0 h1:CRq/00MfruPGFLTQKY8b+8SfdK60TxNztjRMnH0t1Yc=
|
||||
github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
|
||||
github.com/valyala/fasthttp v1.41.0 h1:zeR0Z1my1wDHTRiamBCXVglQdbUwgb9uWG3k1HQz6jY=
|
||||
github.com/valyala/fasthttp v1.41.0/go.mod h1:f6VbjjoI3z1NDOZOv17o6RvtRSWxC77seBFc2uWtgiY=
|
||||
|
@ -512,19 +501,16 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
|
||||
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
|
||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
||||
go.uber.org/zap v1.22.0 h1:Zcye5DUgBloQ9BaT4qc9BnjOFog5TvBSAGkJ3Nf70c0=
|
||||
go.uber.org/zap v1.22.0/go.mod h1:H4siCOZOrAolnUPJEkfaSjDqyP+BDS0DdDWzwcgt3+U=
|
||||
|
@ -709,7 +695,6 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -746,8 +731,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw
|
|||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
|
@ -891,7 +874,6 @@ google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175
|
|||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
@ -1,23 +1,26 @@
|
|||
// Package governor handle the request of governor data from governor endpoint defined in the api.
|
||||
package governor
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/middleware"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/pagination"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Controller definition.
|
||||
type Controller struct {
|
||||
srv *Service
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewController create a new controler.
|
||||
func NewController(serv *Service, logger *zap.Logger) *Controller {
|
||||
return &Controller{srv: serv, logger: logger.With(zap.String("module", "GovernorController"))}
|
||||
}
|
||||
|
||||
// FindGovernorConfigurations handler for the endpoint /governor/config/
|
||||
func (c *Controller) FindGovernorConfigurations(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
governorConfigs, err := c.srv.FindGovernorConfig(ctx.Context(), p)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -25,9 +28,10 @@ func (c *Controller) FindGovernorConfigurations(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(governorConfigs)
|
||||
}
|
||||
|
||||
// FindGovernorConfigurationByGuardianAddress handler for the endpoint /governor/config/:guardian_address.
|
||||
func (c *Controller) FindGovernorConfigurationByGuardianAddress(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
guardianAddress, err := middleware.ExtractGuardianAddress(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
guardianAddress, err := middleware.ExtractGuardianAddress(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -38,8 +42,9 @@ func (c *Controller) FindGovernorConfigurationByGuardianAddress(ctx *fiber.Ctx)
|
|||
return ctx.JSON(govConfig)
|
||||
}
|
||||
|
||||
// FindGovernorStatus handler for the endpoint /governor/status/.
|
||||
func (c *Controller) FindGovernorStatus(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
governorStatus, err := c.srv.FindGovernorStatus(ctx.Context(), p)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -47,9 +52,10 @@ func (c *Controller) FindGovernorStatus(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(governorStatus)
|
||||
}
|
||||
|
||||
// FindGovernorStatusByGuardianAddress handler for the endpoint /governor/status/:guardian_address.
|
||||
func (c *Controller) FindGovernorStatusByGuardianAddress(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
guardianAddress, err := middleware.ExtractGuardianAddress(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
guardianAddress, err := middleware.ExtractGuardianAddress(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -60,8 +66,9 @@ func (c *Controller) FindGovernorStatusByGuardianAddress(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(govStatus)
|
||||
}
|
||||
|
||||
// GetGovernorLimit handler for the endpoint /governor/limit/
|
||||
func (c *Controller) GetGovernorLimit(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
governorLimit, err := c.srv.GetGovernorLimit(ctx.Context(), p)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -69,8 +76,9 @@ func (c *Controller) GetGovernorLimit(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(governorLimit)
|
||||
}
|
||||
|
||||
// FindNotionalLimit handler for the endpoint governor/notional/limit/
|
||||
func (c *Controller) FindNotionalLimit(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
notionalLimit, err := c.srv.FindNotionalLimit(ctx.Context(), p)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -78,9 +86,10 @@ func (c *Controller) FindNotionalLimit(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(notionalLimit)
|
||||
}
|
||||
|
||||
// GetNotionalLimitByChainID handler for the endpoint governor/notional/limit/:chain.
|
||||
func (c *Controller) GetNotionalLimitByChainID(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
chainID, err := middleware.ExtractChainID(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
chainID, err := middleware.ExtractChainID(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -91,8 +100,9 @@ func (c *Controller) GetNotionalLimitByChainID(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(notionalLimit)
|
||||
}
|
||||
|
||||
// GetAvailableNotional handler for the endpoint governor/notional/available/
|
||||
func (c *Controller) GetAvailableNotional(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
notionalAvaialabilies, err := c.srv.GetAvailableNotional(ctx.Context(), p)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -100,9 +110,10 @@ func (c *Controller) GetAvailableNotional(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(notionalAvaialabilies)
|
||||
}
|
||||
|
||||
// GetAvailableNotionalByChainID handler for the endpoint governor/notional/available/:chain
|
||||
func (c *Controller) GetAvailableNotionalByChainID(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
chainID, err := middleware.ExtractChainID(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
chainID, err := middleware.ExtractChainID(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -113,9 +124,10 @@ func (c *Controller) GetAvailableNotionalByChainID(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(response)
|
||||
}
|
||||
|
||||
// GetMaxNotionalAvailableByChainID handler for the endpoint governor/max_available/:chain.
|
||||
func (c *Controller) GetMaxNotionalAvailableByChainID(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
chainID, err := middleware.ExtractChainID(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
chainID, err := middleware.ExtractChainID(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -126,8 +138,9 @@ func (c *Controller) GetMaxNotionalAvailableByChainID(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(response)
|
||||
}
|
||||
|
||||
// GetEnqueueVass handler for the endpoint governor/enqueued_vaas/
|
||||
func (c *Controller) GetEnqueueVass(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
enqueuedVaas, err := c.srv.GetEnqueueVass(ctx.Context(), p)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -135,9 +148,10 @@ func (c *Controller) GetEnqueueVass(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(enqueuedVaas)
|
||||
}
|
||||
|
||||
// GetEnqueueVassByChainID handler for the endpoint governor/enqueued_vaas/:chain.
|
||||
func (c *Controller) GetEnqueueVassByChainID(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
chainID, err := middleware.ExtractChainID(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
chainID, err := middleware.ExtractChainID(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
// Package governor handle the request of governor data from governor endpoint defined in the api.
|
||||
package governor
|
||||
|
||||
import (
|
||||
|
@ -6,7 +7,7 @@ import (
|
|||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
)
|
||||
|
||||
// GovConfigPage definition.
|
||||
// GovConfigPage represent a governor configuration.
|
||||
type GovConfig struct {
|
||||
ID string `bson:"_id" json:"id"`
|
||||
CreatedAt *time.Time `bson:"createdAt" json:"createdAt"`
|
||||
|
@ -29,7 +30,7 @@ type GovConfigfTokens struct {
|
|||
Price float64 `bson:"price" json:"price"`
|
||||
}
|
||||
|
||||
// GovStatusPage definition.
|
||||
// GovStatusPage represent a governor status.
|
||||
type GovStatus struct {
|
||||
ID string `bson:"_id" json:"id"`
|
||||
CreatedAt *time.Time `bson:"createdAt" json:"createdAt"`
|
||||
|
@ -50,17 +51,17 @@ type GovStatusChainEmitter struct {
|
|||
EnqueuedVass interface{} `bson:"enqueuedvaas" json:"enqueuedvaas"`
|
||||
}
|
||||
|
||||
// NotionalLimit definition.
|
||||
// NotionalLimit represent the notional limit value and maximun tranasction size for a chainID.
|
||||
type NotionalLimit struct {
|
||||
ChainID vaa.ChainID `bson:"chainid" json:"chainid"`
|
||||
NotionalLimit *int64 `bson:"notionalLimit" json:"notionalLimit"`
|
||||
MaxTrasactionSize *int64 `bson:"maxTransactionSize" json:"maxTransactionSize"`
|
||||
}
|
||||
|
||||
// NotionalLimitDetail definition.
|
||||
// NotionalLimitDetail represent a notional limit value
|
||||
type NotionalLimitDetail struct {
|
||||
ID string `bson:"_id" json:"id"`
|
||||
ChainID vaa.ChainID `bson:"chainid" json:"chainid"`
|
||||
ChainID vaa.ChainID `bson:"chainId" json:"chainId"`
|
||||
NodeName string `bson:"nodename" json:"nodename"`
|
||||
NotionalLimit *int64 `bson:"notionalLimit" json:"notionalLimit"`
|
||||
MaxTrasactionSize *int64 `bson:"maxTransactionSize" json:"maxTransactionSize"`
|
||||
|
@ -68,11 +69,13 @@ type NotionalLimitDetail struct {
|
|||
UpdatedAt *time.Time `bson:"updatedAt" json:"updatedAt"`
|
||||
}
|
||||
|
||||
// NotionalAvailable represent the available notional for chainID.
|
||||
type NotionalAvailable struct {
|
||||
ChainID vaa.ChainID `bson:"chainid" json:"chainId"`
|
||||
AvailableNotional *int64 `bson:"availableNotional" json:"availableNotional"`
|
||||
}
|
||||
|
||||
// NotionalAvailableDetail represent a notional available value.
|
||||
type NotionalAvailableDetail struct {
|
||||
ID string `bson:"_id" json:"id"`
|
||||
ChainID vaa.ChainID `bson:"chainId" json:"chainId"`
|
||||
|
@ -108,6 +111,7 @@ type EnqueuedVaa struct {
|
|||
TxHash string `bson:"txHash" json:"txHash"`
|
||||
}
|
||||
|
||||
// EnqueuedVaas definition.
|
||||
type EnqueuedVaas struct {
|
||||
ChainID vaa.ChainID `bson:"chainid" json:"chainId"`
|
||||
EnqueuedVaa []*EnqueuedVaa `bson:"enqueuedVaas" json:"enqueuedVaas"`
|
|
@ -1,14 +1,16 @@
|
|||
// Package governor handle the request of governor data from governor endpoint defined in the api.
|
||||
package governor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/pagination"
|
||||
"github.com/pkg/errors"
|
||||
errs "github.com/wormhole-foundation/wormhole-explorer/api/internal/errors"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
|
@ -17,10 +19,7 @@ import (
|
|||
|
||||
const minGuardianNum = 13
|
||||
|
||||
var (
|
||||
ErrWrongQuery = errors.New("MALFORMED_QUERY")
|
||||
)
|
||||
|
||||
// Repository definition.
|
||||
type Repository struct {
|
||||
db *mongo.Database
|
||||
logger *zap.Logger
|
||||
|
@ -30,6 +29,7 @@ type Repository struct {
|
|||
}
|
||||
}
|
||||
|
||||
// NewRepository create a new Repository.
|
||||
func NewRepository(db *mongo.Database, logger *zap.Logger) *Repository {
|
||||
return &Repository{db: db,
|
||||
logger: logger.With(zap.String("module", "GovernorRepository")),
|
||||
|
@ -43,21 +43,25 @@ func NewRepository(db *mongo.Database, logger *zap.Logger) *Repository {
|
|||
}
|
||||
}
|
||||
|
||||
// GovernorQuery respresent a query for the governors mongodb documents.
|
||||
type GovernorQuery struct {
|
||||
pagination.Pagination
|
||||
id string
|
||||
}
|
||||
|
||||
// QueryGovernor create a new GovernorQuery with default pagination values.
|
||||
func QueryGovernor() *GovernorQuery {
|
||||
page := pagination.FirstPage()
|
||||
return &GovernorQuery{Pagination: *page}
|
||||
}
|
||||
|
||||
// SetID set the id field of the GovernorQuery struct.
|
||||
func (q *GovernorQuery) SetID(id string) *GovernorQuery {
|
||||
q.id = id
|
||||
return q
|
||||
}
|
||||
|
||||
// SetPagination set the pagination field of the GovernorQuery struct.
|
||||
func (q *GovernorQuery) SetPagination(p *pagination.Pagination) *GovernorQuery {
|
||||
q.Pagination = *p
|
||||
return q
|
||||
|
@ -71,6 +75,7 @@ func (q *GovernorQuery) toBSON() *bson.D {
|
|||
return &r
|
||||
}
|
||||
|
||||
// FindGovConfigurations get a list of *GovConfig.
|
||||
func (r *Repository) FindGovConfigurations(ctx context.Context, q *GovernorQuery) ([]*GovConfig, error) {
|
||||
if q == nil {
|
||||
q = QueryGovernor()
|
||||
|
@ -87,19 +92,26 @@ func (r *Repository) FindGovConfigurations(ctx context.Context, q *GovernorQuery
|
|||
options := options.Find().SetProjection(projection).SetLimit(q.PageSize).SetSkip(q.Offset).SetSort(sort)
|
||||
cur, err := r.collections.governorConfig.Find(ctx, q.toBSON(), options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Find command to get governor configurations",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
var govConfigs []*GovConfig
|
||||
err = cur.All(ctx, &govConfigs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed decoding cursor to []*GovConfig", zap.Error(err), zap.Any("q", q),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
return govConfigs, err
|
||||
}
|
||||
|
||||
// FindGovConfiguration get a *GovConfig. The q parameter define the filter to apply to the query.
|
||||
func (r *Repository) FindGovConfiguration(ctx context.Context, q *GovernorQuery) (*GovConfig, error) {
|
||||
if q == nil {
|
||||
return nil, ErrWrongQuery
|
||||
return nil, errs.ErrMalformedQuery
|
||||
}
|
||||
var govConfig GovConfig
|
||||
projection := bson.D{
|
||||
|
@ -113,11 +125,18 @@ func (r *Repository) FindGovConfiguration(ctx context.Context, q *GovernorQuery)
|
|||
options := options.FindOne().SetProjection(projection)
|
||||
err := r.collections.governorConfig.FindOne(ctx, q.toBSON(), options).Decode(&govConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
return nil, errs.ErrNotFound
|
||||
}
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute FindOne command to get governor configuration",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
return &govConfig, err
|
||||
}
|
||||
|
||||
// FindGovernorStatus get a list of *GovStatus.
|
||||
func (r *Repository) FindGovernorStatus(ctx context.Context, q *GovernorQuery) ([]*GovStatus, error) {
|
||||
if q == nil {
|
||||
q = QueryGovernor()
|
||||
|
@ -132,19 +151,26 @@ func (r *Repository) FindGovernorStatus(ctx context.Context, q *GovernorQuery) (
|
|||
options := options.Find().SetProjection(projection).SetLimit(q.PageSize).SetSkip(q.Offset).SetSort(sort)
|
||||
cur, err := r.collections.governorStatus.Find(ctx, q.toBSON(), options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Find command to get all governor status",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
var govStatus []*GovStatus
|
||||
err = cur.All(ctx, &govStatus)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed decoding cursor to []*GovStatus", zap.Error(err), zap.Any("q", q),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
return govStatus, err
|
||||
}
|
||||
|
||||
// FindOneGovernorStatus get a *GovStatus. The q parameter define the filter to apply to the query.
|
||||
func (r *Repository) FindOneGovernorStatus(ctx context.Context, q *GovernorQuery) (*GovStatus, error) {
|
||||
if q == nil {
|
||||
return nil, ErrWrongQuery
|
||||
return nil, errs.ErrMalformedQuery
|
||||
}
|
||||
var govConfig GovStatus
|
||||
projection := bson.D{
|
||||
|
@ -156,37 +182,49 @@ func (r *Repository) FindOneGovernorStatus(ctx context.Context, q *GovernorQuery
|
|||
options := options.FindOne().SetProjection(projection)
|
||||
err := r.collections.governorStatus.FindOne(ctx, q.toBSON(), options).Decode(&govConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
return nil, errs.ErrNotFound
|
||||
}
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute FindOne command to get governor status",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
return &govConfig, err
|
||||
}
|
||||
|
||||
// NotionalLimitQuery
|
||||
type NotionalLimitQuery struct {
|
||||
pagination.Pagination
|
||||
id string
|
||||
chainID vaa.ChainID
|
||||
}
|
||||
|
||||
// QueryNotionalLimit create a new NotionalLimitQuery with default pagination values.
|
||||
func QueryNotionalLimit() *NotionalLimitQuery {
|
||||
page := pagination.FirstPage()
|
||||
return &NotionalLimitQuery{Pagination: *page}
|
||||
}
|
||||
|
||||
// SetID set the id field of the NotionalLimitQuery struct.
|
||||
func (q *NotionalLimitQuery) SetID(id string) *NotionalLimitQuery {
|
||||
q.id = id
|
||||
return q
|
||||
}
|
||||
|
||||
// SetChain set the chainID field of the NotionalLimitQuery struct.
|
||||
func (q *NotionalLimitQuery) SetChain(chainID vaa.ChainID) *NotionalLimitQuery {
|
||||
q.chainID = chainID
|
||||
return q
|
||||
}
|
||||
|
||||
// SetPagination set the Pagination field of the NotionalLimitQuery struct.
|
||||
func (q *NotionalLimitQuery) SetPagination(p *pagination.Pagination) *NotionalLimitQuery {
|
||||
q.Pagination = *p
|
||||
return q
|
||||
}
|
||||
|
||||
// FindNotionalLimit get a list *NotionalLimit.
|
||||
func (r *Repository) FindNotionalLimit(ctx context.Context, q *NotionalLimitQuery) ([]*NotionalLimit, error) {
|
||||
// agreggation stages to get notionalLimit for each chainID.
|
||||
matchStage1 := bson.D{{Key: "$match", Value: bson.D{}}}
|
||||
|
@ -259,24 +297,31 @@ func (r *Repository) FindNotionalLimit(ctx context.Context, q *NotionalLimitQuer
|
|||
// execute aggregate operations.
|
||||
cur, err := r.collections.governorConfig.Aggregate(ctx, pipeLine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Aggregate command to get notional limit",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// decodes to NotionalLimit.
|
||||
var notionalLimits []*NotionalLimit
|
||||
err = cur.All(ctx, ¬ionalLimits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed decoding cursor to []*NotionalLimit", zap.Error(err), zap.Any("q", q),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// check records exists.
|
||||
if len(notionalLimits) == 0 {
|
||||
return nil, errors.New("not found")
|
||||
return nil, errs.ErrNotFound
|
||||
}
|
||||
|
||||
return notionalLimits, nil
|
||||
}
|
||||
|
||||
// GetNotionalLimitByChainID get a list *NotionalLimitDetail.
|
||||
func (r *Repository) GetNotionalLimitByChainID(ctx context.Context, q *NotionalLimitQuery) ([]*NotionalLimitDetail, error) {
|
||||
// agreggation stages to get notionalLimit by chainID.
|
||||
matchStage1 := bson.D{{Key: "$match", Value: bson.D{}}}
|
||||
|
@ -333,19 +378,26 @@ func (r *Repository) GetNotionalLimitByChainID(ctx context.Context, q *NotionalL
|
|||
// execute aggregate operations.
|
||||
cur, err := r.collections.governorConfig.Aggregate(ctx, pipeLine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Aggregate command to get notional limit by chainID",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// decode to []NotionalLimitRecord.
|
||||
var notionalLimits []*NotionalLimitDetail
|
||||
err = cur.All(ctx, ¬ionalLimits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed decoding cursor to []*NotionalLimitDetail", zap.Error(err), zap.Any("q", q),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return notionalLimits, nil
|
||||
}
|
||||
|
||||
// GetAvailableNotional get a list of *NotionalAvailable.
|
||||
func (r *Repository) GetAvailableNotional(ctx context.Context, q *NotionalLimitQuery) ([]*NotionalAvailable, error) {
|
||||
// stage.
|
||||
matchStage1 := bson.D{{Key: "$match", Value: bson.D{}}}
|
||||
|
@ -421,24 +473,31 @@ func (r *Repository) GetAvailableNotional(ctx context.Context, q *NotionalLimitQ
|
|||
// execute aggregate operations.
|
||||
cur, err := r.collections.governorStatus.Aggregate(ctx, pipeLine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Aggregate command to get available notional",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// decode to []NotionalLimitRecord.
|
||||
var notionalAvailables []*NotionalAvailable
|
||||
err = cur.All(ctx, ¬ionalAvailables)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed decoding cursor to []*NotionalAvailable", zap.Error(err), zap.Any("q", q),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// check exists records
|
||||
if len(notionalAvailables) == 0 {
|
||||
return nil, errors.New("not found")
|
||||
return nil, errs.ErrNotFound
|
||||
}
|
||||
|
||||
return notionalAvailables, nil
|
||||
}
|
||||
|
||||
// GetAvailableNotionalByChainID get a list of *NotionalAvailableDetail.
|
||||
func (r *Repository) GetAvailableNotionalByChainID(ctx context.Context, q *NotionalLimitQuery) ([]*NotionalAvailableDetail, error) {
|
||||
// stage definitions.
|
||||
matchStage1 := bson.D{{Key: "$match", Value: bson.D{}}}
|
||||
|
@ -497,19 +556,26 @@ func (r *Repository) GetAvailableNotionalByChainID(ctx context.Context, q *Notio
|
|||
// execute aggregate operations.
|
||||
cur, err := r.collections.governorStatus.Aggregate(ctx, pipeLine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Aggregate command to get available notional by chainID",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// decode to []NotionalLimitRecord.
|
||||
var notionalAvailability []*NotionalAvailableDetail
|
||||
err = cur.All(ctx, ¬ionalAvailability)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed decoding cursor to []*NotionalAvailableDetail", zap.Error(err), zap.Any("q", q),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return notionalAvailability, nil
|
||||
}
|
||||
|
||||
// GetMaxNotionalAvailableByChainID get a *MaxNotionalAvailableRecord.
|
||||
func (r *Repository) GetMaxNotionalAvailableByChainID(ctx context.Context, q *NotionalLimitQuery) (*MaxNotionalAvailableRecord, error) {
|
||||
// stage definitions.
|
||||
matchStage1 := bson.D{{Key: "$match", Value: bson.D{}}}
|
||||
|
@ -577,55 +643,67 @@ func (r *Repository) GetMaxNotionalAvailableByChainID(ctx context.Context, q *No
|
|||
// execute aggregate operations.
|
||||
cur, err := r.collections.governorStatus.Aggregate(ctx, pipeLine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Aggregate command to get maximun available notional by chainID",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// decode to []NotionalLimitRecord.
|
||||
var rows []*MaxNotionalAvailableRecord
|
||||
err = cur.All(ctx, &rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed decoding cursor to []*MaxNotionalAvailableRecord", zap.Error(err), zap.Any("q", q),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// check exists records
|
||||
if len(rows) == 0 {
|
||||
return nil, errors.New("not found")
|
||||
return nil, errs.ErrNotFound
|
||||
}
|
||||
|
||||
if len(rows) < minGuardianNum {
|
||||
return nil, errors.New("not found")
|
||||
return nil, errs.ErrNotFound
|
||||
}
|
||||
|
||||
maxNotionalLimit := rows[minGuardianNum-1]
|
||||
return maxNotionalLimit, nil
|
||||
}
|
||||
|
||||
// EnqueuedVaaQuery respresent a query for enqueuedVaa queries.
|
||||
type EnqueuedVaaQuery struct {
|
||||
pagination.Pagination
|
||||
id string
|
||||
chainID vaa.ChainID
|
||||
}
|
||||
|
||||
// QueryEnqueuedVaa create a new EnqueuedVaaQuery with default pagination values.
|
||||
func QueryEnqueuedVaa() *EnqueuedVaaQuery {
|
||||
page := pagination.FirstPage()
|
||||
return &EnqueuedVaaQuery{Pagination: *page}
|
||||
}
|
||||
|
||||
// SetID set the id field of the EnqueuedVaaQuery struct.
|
||||
func (q *EnqueuedVaaQuery) SetID(id string) *EnqueuedVaaQuery {
|
||||
q.id = id
|
||||
return q
|
||||
}
|
||||
|
||||
// SetChain set the chainID field of the EnqueuedVaaQuery struct.
|
||||
func (q *EnqueuedVaaQuery) SetChain(chainID vaa.ChainID) *EnqueuedVaaQuery {
|
||||
q.chainID = chainID
|
||||
return q
|
||||
}
|
||||
|
||||
// SetPagination set the pagination field of the EnqueuedVaaQuery struct.
|
||||
func (q *EnqueuedVaaQuery) SetPagination(p *pagination.Pagination) *EnqueuedVaaQuery {
|
||||
q.Pagination = *p
|
||||
return q
|
||||
}
|
||||
|
||||
// GetEnqueueVass get a list of *EnqueuedVaas.
|
||||
func (r *Repository) GetEnqueueVass(ctx context.Context, q *EnqueuedVaaQuery) ([]*EnqueuedVaas, error) {
|
||||
// match stage.
|
||||
matchStage1 := bson.D{{Key: "$match", Value: bson.D{}}}
|
||||
|
@ -678,7 +756,10 @@ func (r *Repository) GetEnqueueVass(ctx context.Context, q *EnqueuedVaaQuery) ([
|
|||
|
||||
cur, err := r.collections.governorStatus.Aggregate(ctx, pipeLine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Aggregate command to get enqueued vaas",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
var rows []struct {
|
||||
|
@ -697,11 +778,14 @@ func (r *Repository) GetEnqueueVass(ctx context.Context, q *EnqueuedVaaQuery) ([
|
|||
// decode query response.
|
||||
err = cur.All(ctx, &rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed decoding cursor to rows", zap.Error(err), zap.Any("q", q),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
if len(rows) == 0 {
|
||||
return nil, errors.New("not found")
|
||||
return nil, errs.ErrNotFound
|
||||
}
|
||||
|
||||
// TODO: Change this logic to mongo query code.
|
||||
|
@ -732,7 +816,7 @@ func (r *Repository) GetEnqueueVass(ctx context.Context, q *EnqueuedVaaQuery) ([
|
|||
}
|
||||
|
||||
if len(enqueuedVaas) == 0 {
|
||||
return nil, errors.New("not found")
|
||||
return nil, errs.ErrNotFound
|
||||
}
|
||||
|
||||
// group by chainID.
|
||||
|
@ -760,6 +844,7 @@ func (r *Repository) GetEnqueueVass(ctx context.Context, q *EnqueuedVaaQuery) ([
|
|||
return response, nil
|
||||
}
|
||||
|
||||
// GetEnqueueVassByChainID get a list of *EnqueuedVaaDetail by chainID.
|
||||
func (r *Repository) GetEnqueueVassByChainID(ctx context.Context, q *EnqueuedVaaQuery) ([]*EnqueuedVaaDetail, error) {
|
||||
// stage definitions.
|
||||
matchStage1 := bson.D{{Key: "$match", Value: bson.D{}}}
|
||||
|
@ -823,7 +908,10 @@ func (r *Repository) GetEnqueueVassByChainID(ctx context.Context, q *EnqueuedVaa
|
|||
|
||||
cur, err := r.collections.governorStatus.Aggregate(ctx, pipeline)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Aggregate command to get enqueued vaas by chainID",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// decode query response.
|
||||
|
@ -840,7 +928,10 @@ func (r *Repository) GetEnqueueVassByChainID(ctx context.Context, q *EnqueuedVaa
|
|||
}
|
||||
err = cur.All(ctx, &rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed decoding cursor to rows", zap.Error(err), zap.Any("q", q),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// TODO: Change this logic to mongo query code.
|
||||
|
@ -871,7 +962,7 @@ func (r *Repository) GetEnqueueVassByChainID(ctx context.Context, q *EnqueuedVaa
|
|||
}
|
||||
|
||||
if len(response) == 0 {
|
||||
return nil, errors.New("not found")
|
||||
return nil, errs.ErrNotFound
|
||||
}
|
||||
|
||||
// sort response by sequence.
|
||||
|
@ -881,6 +972,7 @@ func (r *Repository) GetEnqueueVassByChainID(ctx context.Context, q *EnqueuedVaa
|
|||
return response, nil
|
||||
}
|
||||
|
||||
// GetGovernorLimit get a list of *GovernorLimit.
|
||||
func (r *Repository) GetGovernorLimit(ctx context.Context, q *GovernorQuery) ([]*GovernorLimit, error) {
|
||||
// lookup.
|
||||
lookupStage1 := bson.D{
|
||||
|
@ -1017,19 +1109,25 @@ func (r *Repository) GetGovernorLimit(ctx context.Context, q *GovernorQuery) ([]
|
|||
// execute aggregate operations.
|
||||
cur, err := r.collections.governorConfig.Aggregate(ctx, pipeLine)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Aggregate command to get governor limit",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// decodes to RawDocRecord.
|
||||
var governorLimits []*GovernorLimit
|
||||
err = cur.All(ctx, &governorLimits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed decoding cursor to []*GovernorLimit", zap.Error(err), zap.Any("q", q),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
// check exists records
|
||||
if len(governorLimits) == 0 {
|
||||
return nil, errors.New("not found")
|
||||
return nil, errs.ErrNotFound
|
||||
}
|
||||
|
||||
return governorLimits, nil
|
|
@ -1,11 +1,12 @@
|
|||
// Package governor handle the request of governor data from governor endpoint defined in the api.
|
||||
package governor
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/pagination"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/services"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/response"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
@ -20,118 +21,118 @@ func NewService(dao *Repository, logger *zap.Logger) *Service {
|
|||
}
|
||||
|
||||
// FindGovernorConfig get a list of governor configurations.
|
||||
func (s *Service) FindGovernorConfig(ctx context.Context, p *pagination.Pagination) (*services.Response[[]*GovConfig], error) {
|
||||
func (s *Service) FindGovernorConfig(ctx context.Context, p *pagination.Pagination) (*response.Response[[]*GovConfig], error) {
|
||||
if p == nil {
|
||||
p = pagination.FirstPage()
|
||||
}
|
||||
query := QueryGovernor().SetPagination(p)
|
||||
govConfigs, err := s.repo.FindGovConfigurations(ctx, query)
|
||||
res := services.Response[[]*GovConfig]{Data: govConfigs, Error: err}
|
||||
res := response.Response[[]*GovConfig]{Data: govConfigs}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// FindGovernorConfigByGuardianAddress get a governor configuration by guardianAddress.
|
||||
func (s *Service) FindGovernorConfigByGuardianAddress(ctx context.Context, guardianAddress string, p *pagination.Pagination) (*services.Response[*GovConfig], error) {
|
||||
func (s *Service) FindGovernorConfigByGuardianAddress(ctx context.Context, guardianAddress string, p *pagination.Pagination) (*response.Response[*GovConfig], error) {
|
||||
query := QueryGovernor().SetID(guardianAddress).SetPagination(p)
|
||||
govConfig, err := s.repo.FindGovConfiguration(ctx, query)
|
||||
res := services.Response[*GovConfig]{Data: govConfig, Error: err}
|
||||
res := response.Response[*GovConfig]{Data: govConfig}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// FindGovernorStatus get a list of governor status.
|
||||
func (s *Service) FindGovernorStatus(ctx context.Context, p *pagination.Pagination) (*services.Response[[]*GovStatus], error) {
|
||||
func (s *Service) FindGovernorStatus(ctx context.Context, p *pagination.Pagination) (*response.Response[[]*GovStatus], error) {
|
||||
if p == nil {
|
||||
p = pagination.FirstPage()
|
||||
}
|
||||
query := QueryGovernor().SetPagination(p)
|
||||
govStatus, err := s.repo.FindGovernorStatus(ctx, query)
|
||||
res := services.Response[[]*GovStatus]{Data: govStatus, Error: err}
|
||||
res := response.Response[[]*GovStatus]{Data: govStatus}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// FindGovernorStatusByGuardianAddress get a governor status by guardianAddress.
|
||||
func (s *Service) FindGovernorStatusByGuardianAddress(ctx context.Context, guardianAddress string, p *pagination.Pagination) (*services.Response[*GovStatus], error) {
|
||||
func (s *Service) FindGovernorStatusByGuardianAddress(ctx context.Context, guardianAddress string, p *pagination.Pagination) (*response.Response[*GovStatus], error) {
|
||||
query := QueryGovernor().SetID(guardianAddress).SetPagination(p)
|
||||
govStatus, err := s.repo.FindOneGovernorStatus(ctx, query)
|
||||
res := services.Response[*GovStatus]{Data: govStatus, Error: err}
|
||||
res := response.Response[*GovStatus]{Data: govStatus}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// FindNotionalLimit get a notional limit for each chainID.
|
||||
func (s *Service) FindNotionalLimit(ctx context.Context, p *pagination.Pagination) (*services.Response[[]*NotionalLimit], error) {
|
||||
func (s *Service) FindNotionalLimit(ctx context.Context, p *pagination.Pagination) (*response.Response[[]*NotionalLimit], error) {
|
||||
if p == nil {
|
||||
p = pagination.FirstPage()
|
||||
}
|
||||
query := QueryNotionalLimit().SetPagination(p)
|
||||
notionalLimit, err := s.repo.FindNotionalLimit(ctx, query)
|
||||
res := services.Response[[]*NotionalLimit]{Data: notionalLimit, Error: err}
|
||||
res := response.Response[[]*NotionalLimit]{Data: notionalLimit}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// GetNotionalLimitByChainID get a notional limit by chainID.
|
||||
func (s *Service) GetNotionalLimitByChainID(ctx context.Context, p *pagination.Pagination, chainID vaa.ChainID) (*services.Response[[]*NotionalLimitDetail], error) {
|
||||
func (s *Service) GetNotionalLimitByChainID(ctx context.Context, p *pagination.Pagination, chainID vaa.ChainID) (*response.Response[[]*NotionalLimitDetail], error) {
|
||||
query := QueryNotionalLimit().SetPagination(p).SetChain(chainID)
|
||||
notionalLimit, err := s.repo.GetNotionalLimitByChainID(ctx, query)
|
||||
res := services.Response[[]*NotionalLimitDetail]{Data: notionalLimit, Error: err}
|
||||
res := response.Response[[]*NotionalLimitDetail]{Data: notionalLimit}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// GetAvailableNotional get a available notional for each chainID.
|
||||
func (s *Service) GetAvailableNotional(ctx context.Context, p *pagination.Pagination) (*services.Response[[]*NotionalAvailable], error) {
|
||||
func (s *Service) GetAvailableNotional(ctx context.Context, p *pagination.Pagination) (*response.Response[[]*NotionalAvailable], error) {
|
||||
if p == nil {
|
||||
p = pagination.FirstPage()
|
||||
}
|
||||
query := QueryNotionalLimit().SetPagination(p)
|
||||
notionalAvailability, err := s.repo.GetAvailableNotional(ctx, query)
|
||||
res := services.Response[[]*NotionalAvailable]{Data: notionalAvailability, Error: err}
|
||||
res := response.Response[[]*NotionalAvailable]{Data: notionalAvailability}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// GetAvailableNotionalByChainID get a available notional by chainID.
|
||||
func (s *Service) GetAvailableNotionalByChainID(ctx context.Context, p *pagination.Pagination, chainID vaa.ChainID) (*services.Response[[]*NotionalAvailableDetail], error) {
|
||||
func (s *Service) GetAvailableNotionalByChainID(ctx context.Context, p *pagination.Pagination, chainID vaa.ChainID) (*response.Response[[]*NotionalAvailableDetail], error) {
|
||||
query := QueryNotionalLimit().SetPagination(p).SetChain(chainID)
|
||||
notionaLAvailability, err := s.repo.GetAvailableNotionalByChainID(ctx, query)
|
||||
res := services.Response[[]*NotionalAvailableDetail]{Data: notionaLAvailability, Error: err}
|
||||
res := response.Response[[]*NotionalAvailableDetail]{Data: notionaLAvailability}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// GetMaxNotionalAvailableByChainID get a maximun notional value by chainID.
|
||||
func (s *Service) GetMaxNotionalAvailableByChainID(ctx context.Context, p *pagination.Pagination, chainID vaa.ChainID) (*services.Response[*MaxNotionalAvailableRecord], error) {
|
||||
func (s *Service) GetMaxNotionalAvailableByChainID(ctx context.Context, p *pagination.Pagination, chainID vaa.ChainID) (*response.Response[*MaxNotionalAvailableRecord], error) {
|
||||
query := QueryNotionalLimit().SetPagination(p).SetChain(chainID)
|
||||
maxNotionaLAvailable, err := s.repo.GetMaxNotionalAvailableByChainID(ctx, query)
|
||||
res := services.Response[*MaxNotionalAvailableRecord]{Data: maxNotionaLAvailable, Error: err}
|
||||
res := response.Response[*MaxNotionalAvailableRecord]{Data: maxNotionaLAvailable}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// GetEnqueueVass.
|
||||
func (s *Service) GetEnqueueVass(ctx context.Context, p *pagination.Pagination) (*services.Response[[]*EnqueuedVaas], error) {
|
||||
// GetEnqueueVaas get all the enqueued vaa.
|
||||
func (s *Service) GetEnqueueVass(ctx context.Context, p *pagination.Pagination) (*response.Response[[]*EnqueuedVaas], error) {
|
||||
if p == nil {
|
||||
p = pagination.FirstPage()
|
||||
}
|
||||
query := QueryEnqueuedVaa().SetPagination(p)
|
||||
enqueuedVaaResponse, err := s.repo.GetEnqueueVass(ctx, query)
|
||||
res := services.Response[[]*EnqueuedVaas]{Data: enqueuedVaaResponse, Error: err}
|
||||
res := response.Response[[]*EnqueuedVaas]{Data: enqueuedVaaResponse}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// GetEnqueueVassByChainID by chainID.
|
||||
func (s *Service) GetEnqueueVassByChainID(ctx context.Context, p *pagination.Pagination, chainID vaa.ChainID) (*services.Response[[]*EnqueuedVaaDetail], error) {
|
||||
// GetEnqueueVassByChainID get enequeued vaa by chainID.
|
||||
func (s *Service) GetEnqueueVassByChainID(ctx context.Context, p *pagination.Pagination, chainID vaa.ChainID) (*response.Response[[]*EnqueuedVaaDetail], error) {
|
||||
if p == nil {
|
||||
p = pagination.FirstPage()
|
||||
}
|
||||
query := QueryEnqueuedVaa().SetPagination(p).SetChain(chainID)
|
||||
enqueuedVaaRecord, err := s.repo.GetEnqueueVassByChainID(ctx, query)
|
||||
res := services.Response[[]*EnqueuedVaaDetail]{Data: enqueuedVaaRecord, Error: err}
|
||||
res := response.Response[[]*EnqueuedVaaDetail]{Data: enqueuedVaaRecord}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
// GetGovernorLimit get governor limit.
|
||||
func (s *Service) GetGovernorLimit(ctx context.Context, p *pagination.Pagination) (*services.Response[[]*GovernorLimit], error) {
|
||||
func (s *Service) GetGovernorLimit(ctx context.Context, p *pagination.Pagination) (*response.Response[[]*GovernorLimit], error) {
|
||||
if p == nil {
|
||||
p = pagination.FirstPage()
|
||||
}
|
||||
query := QueryGovernor().SetPagination(p)
|
||||
governorLimit, err := s.repo.GetGovernorLimit(ctx, query)
|
||||
res := services.Response[[]*GovernorLimit]{Data: governorLimit, Error: err}
|
||||
res := response.Response[[]*GovernorLimit]{Data: governorLimit}
|
||||
return &res, err
|
||||
}
|
|
@ -1,19 +1,19 @@
|
|||
// Package observations handle the request of observations data from governor endpoint defined in the api.
|
||||
package observations
|
||||
|
||||
import (
|
||||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/errors"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/middleware"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/pagination"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Controller definition.
|
||||
type Controller struct {
|
||||
srv *Service
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewController create a new controler.
|
||||
func NewController(srv *Service, logger *zap.Logger) *Controller {
|
||||
return &Controller{
|
||||
srv: srv,
|
||||
|
@ -21,8 +21,9 @@ func NewController(srv *Service, logger *zap.Logger) *Controller {
|
|||
}
|
||||
}
|
||||
|
||||
// FindAll handler for the endpoint /observations/.
|
||||
func (c *Controller) FindAll(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
obs, err := c.srv.FindAll(ctx.Context(), p)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -30,9 +31,13 @@ func (c *Controller) FindAll(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(obs)
|
||||
}
|
||||
|
||||
// FindAllByChain handler for the endpoint /observations/:chain.
|
||||
func (c *Controller) FindAllByChain(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
chainID, err := middleware.ExtractChainID(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
chainID, err := middleware.ExtractChainID(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
obs, err := c.srv.FindByChain(ctx.Context(), chainID, p)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -40,12 +45,14 @@ func (c *Controller) FindAllByChain(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(obs)
|
||||
}
|
||||
|
||||
// FindAllByEmitter handler for the endpoint /observations/:chain/:emitter.
|
||||
func (c *Controller) FindAllByEmitter(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
chainID, addr, _, err := middleware.ExtractVAAParams(ctx)
|
||||
if errors.IsOf(err, middleware.ErrMalformedChain, middleware.ErrMalformedAddr) {
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
chainID, addr, err := middleware.ExtractVAAChainIDEmitter(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
obs, err := c.srv.FindByEmitter(ctx.Context(), chainID, addr, p)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -53,9 +60,10 @@ func (c *Controller) FindAllByEmitter(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(obs)
|
||||
}
|
||||
|
||||
// FindAllByVAA handler for the endpoint /observations/:chain/:emitter/:sequence
|
||||
func (c *Controller) FindAllByVAA(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
chainID, addr, seq, err := middleware.ExtractVAAParams(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
chainID, addr, seq, err := middleware.ExtractVAAParams(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -66,18 +74,21 @@ func (c *Controller) FindAllByVAA(ctx *fiber.Ctx) error {
|
|||
return ctx.JSON(obs)
|
||||
}
|
||||
|
||||
// FindOne handler for the endpoint /observations/:chain/:emitter/:sequence/:signer/:hash
|
||||
func (c *Controller) FindOne(ctx *fiber.Ctx) error {
|
||||
chainID, addr, seq, err := middleware.ExtractVAAParams(ctx)
|
||||
chainID, addr, seq, err := middleware.ExtractVAAParams(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signer := ctx.Params("signer")
|
||||
signerAddr, err := vaa.StringToAddress(signer)
|
||||
signerAddr, err := middleware.ExtractObservationSigner(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hash := ctx.Params("hash")
|
||||
obs, err := c.srv.FindOne(ctx.Context(), chainID, addr, seq, &signerAddr, []byte(hash))
|
||||
hash, err := middleware.ExtractObservationHash(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
obs, err := c.srv.FindOne(ctx.Context(), chainID, addr, seq, signerAddr, []byte(hash))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
|
@ -1,10 +1,13 @@
|
|||
// Package observations handle the request of observations data from governor endpoint defined in the api.
|
||||
package observations
|
||||
|
||||
import (
|
||||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
"time"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
)
|
||||
|
||||
// ObservationDoc represent an observation document.
|
||||
type ObservationDoc struct {
|
||||
ID string `bson:"_id" json:"id"`
|
||||
Version uint8 `bson:"version" json:"version"`
|
||||
|
@ -15,7 +18,6 @@ type ObservationDoc struct {
|
|||
TxHash []byte `bson:"txHash" json:"txHash"`
|
||||
GuardianAddr string `bson:"guardianAddr" json:"guardianAddr"`
|
||||
Signature []byte `bson:"signature" json:"signature"`
|
||||
|
||||
UpdatedAt *time.Time `bson:"updatedAt" json:"updatedAt"`
|
||||
IndexedAt *time.Time `bson:"indexedAt" json:"indexedAt"`
|
||||
}
|
|
@ -1,16 +1,21 @@
|
|||
// Package observations handle the request of observations data from governor endpoint defined in the api.
|
||||
package observations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/pagination"
|
||||
"github.com/pkg/errors"
|
||||
errs "github.com/wormhole-foundation/wormhole-explorer/api/internal/errors"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Repository definition.
|
||||
type Repository struct {
|
||||
db *mongo.Database
|
||||
logger *zap.Logger
|
||||
|
@ -19,6 +24,7 @@ type Repository struct {
|
|||
}
|
||||
}
|
||||
|
||||
// NewRepository create a new Repository.
|
||||
func NewRepository(db *mongo.Database, logger *zap.Logger) *Repository {
|
||||
return &Repository{db: db,
|
||||
logger: logger.With(zap.String("module", "ObservationsRepository")),
|
||||
|
@ -26,6 +32,8 @@ func NewRepository(db *mongo.Database, logger *zap.Logger) *Repository {
|
|||
}
|
||||
}
|
||||
|
||||
// Find get a list of ObservationDoc pointers.
|
||||
// The input parameter [q *ObservationQuery] define the filters to apply in the query.
|
||||
func (r *Repository) Find(ctx context.Context, q *ObservationQuery) ([]*ObservationDoc, error) {
|
||||
if q == nil {
|
||||
q = Query()
|
||||
|
@ -33,32 +41,43 @@ func (r *Repository) Find(ctx context.Context, q *ObservationQuery) ([]*Observat
|
|||
sort := bson.D{{q.SortBy, q.GetSortInt()}}
|
||||
cur, err := r.collections.observations.Find(ctx, q.toBSON(), options.Find().SetLimit(q.PageSize).SetSkip(q.Offset).SetSort(sort))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Find command to get observations",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
var obs []*ObservationDoc
|
||||
err = cur.All(ctx, &obs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed decoding cursor to []*ObservationDoc", zap.Error(err), zap.Any("q", q),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
return obs, err
|
||||
}
|
||||
|
||||
var (
|
||||
ErrWrongQuery = errors.New("MALFORMED_QUERY")
|
||||
)
|
||||
|
||||
// Find get ObservationDoc pointer.
|
||||
// The input parameter [q *ObservationQuery] define the filters to apply in the query.
|
||||
func (r *Repository) FindOne(ctx context.Context, q *ObservationQuery) (*ObservationDoc, error) {
|
||||
if q == nil {
|
||||
return nil, ErrWrongQuery
|
||||
return nil, errs.ErrMalformedQuery
|
||||
}
|
||||
var obs ObservationDoc
|
||||
err := r.collections.observations.FindOne(ctx, q.toBSON()).Decode(&obs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
return nil, errs.ErrNotFound
|
||||
}
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute FindOne command to get observations",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
return &obs, err
|
||||
}
|
||||
|
||||
// ObservationQuery respresent a query for the observation mongodb document.
|
||||
type ObservationQuery struct {
|
||||
pagination.Pagination
|
||||
chainId vaa.ChainID
|
||||
|
@ -69,36 +88,43 @@ type ObservationQuery struct {
|
|||
uint64
|
||||
}
|
||||
|
||||
// Query create a new ObservationQuery with default pagination vaues.
|
||||
func Query() *ObservationQuery {
|
||||
page := pagination.FirstPage()
|
||||
return &ObservationQuery{Pagination: *page}
|
||||
}
|
||||
|
||||
// SetEmitter set the chainId field of the ObservationQuery struct.
|
||||
func (q *ObservationQuery) SetChain(chainID vaa.ChainID) *ObservationQuery {
|
||||
q.chainId = chainID
|
||||
return q
|
||||
}
|
||||
|
||||
// SetEmitter set the emitter field of the ObservationQuery struct.
|
||||
func (q *ObservationQuery) SetEmitter(emitter string) *ObservationQuery {
|
||||
q.emitter = emitter
|
||||
return q
|
||||
}
|
||||
|
||||
// SetSequence set the sequence field of the ObservationQuery struct.
|
||||
func (q *ObservationQuery) SetSequence(seq uint64) *ObservationQuery {
|
||||
q.sequence = seq
|
||||
return q
|
||||
}
|
||||
|
||||
// SetGuardianAddr set the guardianAddr field of the ObservationQuery struct.
|
||||
func (q *ObservationQuery) SetGuardianAddr(guardianAddr string) *ObservationQuery {
|
||||
q.guardianAddr = guardianAddr
|
||||
return q
|
||||
}
|
||||
|
||||
// SetHash set the hash field of the ObservationQuery struct.
|
||||
func (q *ObservationQuery) SetHash(hash []byte) *ObservationQuery {
|
||||
q.hash = hash
|
||||
return q
|
||||
}
|
||||
|
||||
// SetPagination set the pagination field of the ObservationQuery struct.
|
||||
func (q *ObservationQuery) SetPagination(p *pagination.Pagination) *ObservationQuery {
|
||||
q.Pagination = *p
|
||||
return q
|
|
@ -1,40 +1,49 @@
|
|||
// Package observations handle the request of observations data from governor endpoint defined in the api.
|
||||
package observations
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/pagination"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Service definition.
|
||||
type Service struct {
|
||||
repo *Repository
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewService create a new Service.
|
||||
func NewService(dao *Repository, logger *zap.Logger) *Service {
|
||||
return &Service{repo: dao, logger: logger.With(zap.String("module", "ObservationsService"))}
|
||||
}
|
||||
|
||||
// FindAll get all the observations.
|
||||
func (s *Service) FindAll(ctx context.Context, p *pagination.Pagination) ([]*ObservationDoc, error) {
|
||||
return s.repo.Find(ctx, Query().SetPagination(p))
|
||||
}
|
||||
|
||||
// FindByChain get all the observations by chainID.
|
||||
func (s *Service) FindByChain(ctx context.Context, chain vaa.ChainID, p *pagination.Pagination) ([]*ObservationDoc, error) {
|
||||
query := Query().SetChain(chain).SetPagination(p)
|
||||
return s.repo.Find(ctx, query)
|
||||
}
|
||||
|
||||
// FindByEmitter get all the observations by chainID and emitter address.
|
||||
func (s *Service) FindByEmitter(ctx context.Context, chain vaa.ChainID, emitter *vaa.Address, p *pagination.Pagination) ([]*ObservationDoc, error) {
|
||||
query := Query().SetChain(chain).SetEmitter(emitter.String()).SetPagination(p)
|
||||
return s.repo.Find(ctx, query)
|
||||
}
|
||||
|
||||
// FindByVAA get all the observations for a VAA (chainID, emitter addrress and sequence number).
|
||||
func (s *Service) FindByVAA(ctx context.Context, chain vaa.ChainID, emitter *vaa.Address, seq uint64, p *pagination.Pagination) ([]*ObservationDoc, error) {
|
||||
query := Query().SetChain(chain).SetEmitter(emitter.String()).SetSequence(seq).SetPagination(p)
|
||||
return s.repo.Find(ctx, query)
|
||||
}
|
||||
|
||||
// FindOne get a observation by chainID, emitter address, sequence, signer address and hash.
|
||||
func (s *Service) FindOne(ctx context.Context, chainID vaa.ChainID, emitterAddr *vaa.Address, seq uint64, signerAddr *vaa.Address, hash []byte) (*ObservationDoc, error) {
|
||||
query := Query().SetChain(chainID).SetEmitter(emitterAddr.String()).SetSequence(seq).SetGuardianAddr(signerAddr.String()).SetHash(hash)
|
||||
return s.repo.FindOne(ctx, query)
|
|
@ -1,83 +1,86 @@
|
|||
// Package observations handle the request of VAA data from governor endpoint defined in the api.
|
||||
package vaa
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/errors"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/middleware"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/pagination"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Controller definition.
|
||||
type Controller struct {
|
||||
srv *Service
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewController create a new controler.
|
||||
func NewController(serv *Service, logger *zap.Logger) *Controller {
|
||||
return &Controller{srv: serv, logger: logger.With(zap.String("module", "VaaController"))}
|
||||
}
|
||||
|
||||
// FindAll handler for the endpoint /vaas/.
|
||||
func (c *Controller) FindAll(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
vaas, err := c.srv.FindAll(ctx.Context(), p)
|
||||
if err != nil {
|
||||
fmt.Printf("error finding vaas: %v", err)
|
||||
return err
|
||||
}
|
||||
return ctx.JSON(vaas)
|
||||
}
|
||||
|
||||
// FindByChain handler for the endpoint /vaas/:chain.
|
||||
func (c *Controller) FindByChain(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
chainID, err := middleware.ExtractChainID(ctx)
|
||||
|
||||
fmt.Println(ctx.Locals("requestid"))
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
chainID, err := middleware.ExtractChainID(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vaas, err := c.srv.FindByChain(ctx.Context(), chainID, p)
|
||||
if err != nil {
|
||||
fmt.Printf("error finding vaas: %v", err)
|
||||
return err
|
||||
}
|
||||
return ctx.JSON(vaas)
|
||||
}
|
||||
|
||||
// FindByEmitter handler for the endpoint /vaas/:chain/:emitter.
|
||||
func (c *Controller) FindByEmitter(ctx *fiber.Ctx) error {
|
||||
p := pagination.GetFromContext(ctx)
|
||||
chainID, emitter, _, err := middleware.ExtractVAAParams(ctx)
|
||||
if errors.IsOf(err, middleware.ErrMalformedChain, middleware.ErrMalformedAddr) {
|
||||
p := middleware.GetPaginationFromContext(ctx)
|
||||
chainID, emitter, err := middleware.ExtractVAAChainIDEmitter(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vaas, err := c.srv.FindByEmitter(ctx.Context(), chainID, *emitter, p)
|
||||
if err != nil {
|
||||
//TODO logging
|
||||
fmt.Printf("error finding vaas: %v", err)
|
||||
return err
|
||||
}
|
||||
return ctx.JSON(vaas)
|
||||
}
|
||||
|
||||
// FindById handler for the endpoint /vaas/:chain/:emitter/:sequence/:signer/:hash.
|
||||
func (c *Controller) FindById(ctx *fiber.Ctx) error {
|
||||
chainID, emitter, seq, err := middleware.ExtractVAAParams(ctx)
|
||||
chainID, emitter, seq, err := middleware.ExtractVAAParams(ctx, c.logger)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vaa, err := c.srv.FindById(ctx.Context(), chainID, *emitter, seq)
|
||||
if err != nil {
|
||||
//TODO logging
|
||||
fmt.Printf("error finding vaa: %v", err)
|
||||
return err
|
||||
}
|
||||
return ctx.JSON(vaa)
|
||||
}
|
||||
|
||||
// FindSignedVAAByID get a signedVAA []byte from a chainID, emitter address and sequence.
|
||||
func (c *Controller) FindSignedVAAByID(ctx *fiber.Ctx) error {
|
||||
chainID, emitter, seq, err := middleware.ExtractVAAParams(ctx)
|
||||
chainID, emitter, seq, err := middleware.ExtractVAAParams(ctx, c.logger)
|
||||
if err != nil {
|
||||
// TODO: Handle InvalidArgument code (3) in the response.
|
||||
return err
|
||||
}
|
||||
vaa, err := c.srv.FindById(ctx.Context(), chainID, *emitter, seq)
|
||||
if err != nil {
|
||||
// TODO: handle not found(5) and internal(13) response code.
|
||||
return err
|
||||
}
|
||||
response := struct {
|
|
@ -1,10 +1,12 @@
|
|||
package vaa
|
||||
|
||||
import (
|
||||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
"time"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
)
|
||||
|
||||
// VaaDoc represent an vaa document.
|
||||
type VaaDoc struct {
|
||||
ID string `bson:"_id" json:"id"`
|
||||
Version uint8 `bson:"version" json:"version"`
|
|
@ -2,15 +2,19 @@ package vaa
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/pagination"
|
||||
"github.com/pkg/errors"
|
||||
errs "github.com/wormhole-foundation/wormhole-explorer/api/internal/errors"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Repository definition
|
||||
type Repository struct {
|
||||
db *mongo.Database
|
||||
logger *zap.Logger
|
||||
|
@ -20,6 +24,7 @@ type Repository struct {
|
|||
}
|
||||
}
|
||||
|
||||
// NewRepository create a new Repository.
|
||||
func NewRepository(db *mongo.Database, logger *zap.Logger) *Repository {
|
||||
return &Repository{db: db,
|
||||
logger: logger.With(zap.String("module", "VaaRepository")),
|
||||
|
@ -29,6 +34,8 @@ func NewRepository(db *mongo.Database, logger *zap.Logger) *Repository {
|
|||
}{vaas: db.Collection("vaas"), invalidVaas: db.Collection("invalid_vaas")}}
|
||||
}
|
||||
|
||||
// Find get a list of *VaaDoc.
|
||||
// The input parameter [q *VaaQuery] define the filters to apply in the query.
|
||||
func (r *Repository) Find(ctx context.Context, q *VaaQuery) ([]*VaaDoc, error) {
|
||||
if q == nil {
|
||||
q = Query()
|
||||
|
@ -36,22 +43,37 @@ func (r *Repository) Find(ctx context.Context, q *VaaQuery) ([]*VaaDoc, error) {
|
|||
sort := bson.D{{q.SortBy, q.GetSortInt()}}
|
||||
cur, err := r.collections.vaas.Find(ctx, q.toBSON(), options.Find().SetLimit(q.PageSize).SetSkip(q.Offset).SetSort(sort))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Find command to get vaas",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
var vaas []*VaaDoc
|
||||
err = cur.All(ctx, &vaas)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed decoding cursor to []*VaaDoc", zap.Error(err), zap.Any("q", q),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
return vaas, err
|
||||
}
|
||||
|
||||
// FindOne get *VaaDoc.
|
||||
// The input parameter [q *VaaQuery] define the filters to apply in the query.
|
||||
func (r *Repository) FindOne(ctx context.Context, q *VaaQuery) (*VaaDoc, error) {
|
||||
var vaaDoc VaaDoc
|
||||
err := r.collections.vaas.FindOne(ctx, q.toBSON()).Decode(&vaaDoc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if errors.Is(err, mongo.ErrNoDocuments) {
|
||||
return nil, errs.ErrNotFound
|
||||
}
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute FindOne command to get vaas",
|
||||
zap.Error(err), zap.Any("q", q), zap.String("requestID", requestID))
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return &vaaDoc, err
|
||||
}
|
||||
|
||||
|
@ -64,6 +86,9 @@ func (r *Repository) FindStats(ctx context.Context) ([]*VaaStats, error) {
|
|||
}
|
||||
c, err := r.collections.vaas.Aggregate(ctx, mongo.Pipeline{group})
|
||||
if err != nil {
|
||||
requestID := fmt.Sprintf("%v", ctx.Value("requestid"))
|
||||
r.logger.Error("failed execute Aggregate command to get vaa stats",
|
||||
zap.Error(err), zap.String("requestID", requestID))
|
||||
return nil, err
|
||||
}
|
||||
var stats []*VaaStats
|
||||
|
@ -71,6 +96,7 @@ func (r *Repository) FindStats(ctx context.Context) ([]*VaaStats, error) {
|
|||
return stats, err
|
||||
}
|
||||
|
||||
// VaaQuery respresent a query for the vaa mongodb document.
|
||||
type VaaQuery struct {
|
||||
pagination.Pagination
|
||||
chainId vaa.ChainID
|
||||
|
@ -78,26 +104,31 @@ type VaaQuery struct {
|
|||
sequence uint64
|
||||
}
|
||||
|
||||
// Query create a new VaaQuery with default pagination vaues.
|
||||
func Query() *VaaQuery {
|
||||
page := pagination.FirstPage()
|
||||
return &VaaQuery{Pagination: *page}
|
||||
}
|
||||
|
||||
// SetChain set the chainId field of the VaaQuery struct.
|
||||
func (q *VaaQuery) SetChain(chainID vaa.ChainID) *VaaQuery {
|
||||
q.chainId = chainID
|
||||
return q
|
||||
}
|
||||
|
||||
// SetEmitter set the emitter field of the VaaQuery struct.
|
||||
func (q *VaaQuery) SetEmitter(emitter string) *VaaQuery {
|
||||
q.emitter = emitter
|
||||
return q
|
||||
}
|
||||
|
||||
// SetSequence set the sequence field of the VaaQuery struct.
|
||||
func (q *VaaQuery) SetSequence(seq uint64) *VaaQuery {
|
||||
q.sequence = seq
|
||||
return q
|
||||
}
|
||||
|
||||
// SetPagination set the pagination field of the VaaQuery struct.
|
||||
func (q *VaaQuery) SetPagination(p *pagination.Pagination) *VaaQuery {
|
||||
q.Pagination = *p
|
||||
return q
|
|
@ -4,54 +4,60 @@ import (
|
|||
"context"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/pagination"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/services"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/response"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// Service definition.
|
||||
type Service struct {
|
||||
repo *Repository
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewService create a new Service.
|
||||
func NewService(r *Repository, logger *zap.Logger) *Service {
|
||||
return &Service{repo: r, logger: logger.With(zap.String("module", "VaaService"))}
|
||||
}
|
||||
|
||||
func (s *Service) FindAll(ctx context.Context, p *pagination.Pagination) (*services.Response[[]*VaaDoc], error) {
|
||||
// FindAll get all the the vaa.
|
||||
func (s *Service) FindAll(ctx context.Context, p *pagination.Pagination) (*response.Response[[]*VaaDoc], error) {
|
||||
if p == nil {
|
||||
p = pagination.FirstPage()
|
||||
}
|
||||
|
||||
query := Query().SetPagination(p)
|
||||
vaas, err := s.repo.Find(ctx, query)
|
||||
res := services.Response[[]*VaaDoc]{Data: vaas, Error: err}
|
||||
res := response.Response[[]*VaaDoc]{Data: vaas}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
func (s *Service) FindByChain(ctx context.Context, chain vaa.ChainID, p *pagination.Pagination) (*services.Response[[]*VaaDoc], error) {
|
||||
// FindByChain get all the vaa by chainID.
|
||||
func (s *Service) FindByChain(ctx context.Context, chain vaa.ChainID, p *pagination.Pagination) (*response.Response[[]*VaaDoc], error) {
|
||||
query := Query().SetChain(chain).SetPagination(p)
|
||||
vaas, err := s.repo.Find(ctx, query)
|
||||
res := services.Response[[]*VaaDoc]{Data: vaas, Error: err}
|
||||
res := response.Response[[]*VaaDoc]{Data: vaas}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
func (s *Service) FindByEmitter(ctx context.Context, chain vaa.ChainID, emitter vaa.Address, p *pagination.Pagination) (*services.Response[[]*VaaDoc], error) {
|
||||
// FindByEmitter get all the vaa by chainID and emitter address.
|
||||
func (s *Service) FindByEmitter(ctx context.Context, chain vaa.ChainID, emitter vaa.Address, p *pagination.Pagination) (*response.Response[[]*VaaDoc], error) {
|
||||
query := Query().SetChain(chain).SetEmitter(emitter.String()).SetPagination(p)
|
||||
vaas, err := s.repo.Find(ctx, query)
|
||||
res := services.Response[[]*VaaDoc]{Data: vaas, Error: err}
|
||||
res := response.Response[[]*VaaDoc]{Data: vaas}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
func (s *Service) FindById(ctx context.Context, chain vaa.ChainID, emitter vaa.Address, seq uint64) (*services.Response[*VaaDoc], error) {
|
||||
// FindById get a vaa by chainID, emitter address and sequence number.
|
||||
func (s *Service) FindById(ctx context.Context, chain vaa.ChainID, emitter vaa.Address, seq uint64) (*response.Response[*VaaDoc], error) {
|
||||
query := Query().SetChain(chain).SetEmitter(emitter.String()).SetSequence(seq)
|
||||
vaas, err := s.repo.FindOne(ctx, query)
|
||||
res := services.Response[*VaaDoc]{Data: vaas, Error: err}
|
||||
res := response.Response[*VaaDoc]{Data: vaas}
|
||||
return &res, err
|
||||
}
|
||||
|
||||
func (s *Service) GetVAAStats(ctx context.Context) (*services.Response[[]*VaaStats], error) {
|
||||
func (s *Service) GetVAAStats(ctx context.Context) (*response.Response[[]*VaaStats], error) {
|
||||
stats, err := s.repo.FindStats(ctx)
|
||||
res := services.Response[[]*VaaStats]{Data: stats, Error: err}
|
||||
res := response.Response[[]*VaaStats]{Data: stats}
|
||||
return &res, err
|
||||
}
|
|
@ -1,13 +1,23 @@
|
|||
// Package config implement a simple configuration package.
|
||||
// It define a type [AppConfig] that represent the aplication configuration and
|
||||
// use viper [https://github.com/spf13/viper] to load the configuration.
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
ipfslog "github.com/ipfs/go-log/v2"
|
||||
"github.com/spf13/viper"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
RunModeProduction = "PRODUCTION"
|
||||
RunModeDevelopmernt = "DEVELOPMENT"
|
||||
)
|
||||
|
||||
// AppConfig defines the configuration for the app.
|
||||
type AppConfig struct {
|
||||
DB struct {
|
||||
URL string
|
||||
|
@ -16,10 +26,11 @@ type AppConfig struct {
|
|||
}
|
||||
|
||||
PORT int
|
||||
|
||||
LogLevel string
|
||||
RunMode string
|
||||
}
|
||||
|
||||
// GetLogLevel get zapcore.Level define in the configuraion.
|
||||
func (cfg *AppConfig) GetLogLevel() (ipfslog.LogLevel, error) {
|
||||
return ipfslog.LevelFromString(cfg.LogLevel)
|
||||
}
|
||||
|
@ -27,6 +38,8 @@ func (cfg *AppConfig) GetLogLevel() (ipfslog.LogLevel, error) {
|
|||
func init() {
|
||||
viper.SetDefault("port", 8000)
|
||||
viper.SetDefault("loglevel", "INFO")
|
||||
viper.SetDefault("runmode", "PRODUCTION")
|
||||
|
||||
// Consider environment variables in unmarshall doesn't work unless doing this: https://github.com/spf13/viper/issues/188#issuecomment-1168898503
|
||||
b, err := json.Marshal(AppConfig{})
|
||||
if err != nil {
|
||||
|
@ -50,6 +63,7 @@ func init() {
|
|||
viper.AutomaticEnv()
|
||||
}
|
||||
|
||||
// Get returns the app configuration.
|
||||
func Get() (*AppConfig, error) {
|
||||
var cfg AppConfig
|
||||
err := viper.Unmarshal(&cfg)
|
|
@ -1,11 +1,14 @@
|
|||
// Package db handle mongodb connections.
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// Connect create a new mongo db client for the options defined in the input param url.
|
||||
func Connect(ctx context.Context, url string) (*mongo.Client, error) {
|
||||
cli, err := mongo.NewClient(options.Client().ApplyURI(url))
|
||||
if err != nil {
|
|
@ -0,0 +1,10 @@
|
|||
package errors
|
||||
|
||||
import "errors"
|
||||
|
||||
// Error definitions to use in service and repository layers.
|
||||
var (
|
||||
ErrMalformedQuery = errors.New("MALFORMED_QUERY")
|
||||
ErrNotFound = errors.New("NOT FOUND")
|
||||
ErrInternalError = errors.New("INTERNAL ERROR")
|
||||
)
|
|
@ -1,5 +1,6 @@
|
|||
package pagination
|
||||
|
||||
// Pagination definition.
|
||||
type Pagination struct {
|
||||
Offset int64
|
||||
PageSize int64
|
||||
|
@ -7,41 +8,49 @@ type Pagination struct {
|
|||
SortBy string
|
||||
}
|
||||
|
||||
// FirstPage return a *Pagination with default values offset and page size.
|
||||
func FirstPage() *Pagination {
|
||||
return &Pagination{Offset: 0, PageSize: 50}
|
||||
}
|
||||
|
||||
// BuildPagination create a new *Pagination.
|
||||
func BuildPagination(page, pageSize int64, sortOrder, sortBy string) *Pagination {
|
||||
p := Pagination{}
|
||||
p.SetPage(page).SetPageSize(pageSize).SetSortOrder(sortOrder).SetSortBy(sortBy)
|
||||
return &p
|
||||
}
|
||||
|
||||
// SetPageSize set the PageSize field of the Pagination struct.
|
||||
func (p *Pagination) SetPageSize(limit int64) *Pagination {
|
||||
p.PageSize = limit
|
||||
return p
|
||||
}
|
||||
|
||||
// SetOffset set the Offset field of the Pagination struct.
|
||||
func (p *Pagination) SetOffset(offset int64) *Pagination {
|
||||
p.Offset = offset
|
||||
return p
|
||||
}
|
||||
|
||||
// SetPage set the Page field of the Pagination struct.
|
||||
func (p *Pagination) SetPage(page int64) *Pagination {
|
||||
p.Offset = page * p.PageSize
|
||||
return p
|
||||
}
|
||||
|
||||
// SetSortOrder set the SortOrder field of the Pagination struct.
|
||||
func (p *Pagination) SetSortOrder(order string) *Pagination {
|
||||
p.SortOrder = order
|
||||
return p
|
||||
}
|
||||
|
||||
// SetSortBy set the SortBy field of the Pagination struct.
|
||||
func (p *Pagination) SetSortBy(by string) *Pagination {
|
||||
p.SortBy = by
|
||||
return p
|
||||
}
|
||||
|
||||
// GetSortInt mapping to mongodb sort values.
|
||||
func (p *Pagination) GetSortInt() int {
|
||||
if p.SortOrder == "ASC" {
|
||||
return 1
|
18
api/main.go
18
api/main.go
|
@ -14,12 +14,13 @@ import (
|
|||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/gofiber/fiber/v2/middleware/requestid"
|
||||
ipfslog "github.com/ipfs/go-log/v2"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/config"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/db"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/governor"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/governor"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/observations"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/handlers/vaa"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/config"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/db"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/middleware"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/observations"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/vaa"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/response"
|
||||
)
|
||||
|
||||
var cacheConfig = cache.Config{
|
||||
|
@ -54,7 +55,7 @@ func main() {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
rootLogger := ipfslog.Logger("wormhole-spy").Desugar()
|
||||
rootLogger := ipfslog.Logger("wormhole-api").Desugar()
|
||||
ipfslog.SetAllLoggers(lvl)
|
||||
|
||||
// Setup DB
|
||||
|
@ -79,8 +80,9 @@ func main() {
|
|||
observationsCtrl := observations.NewController(obsService, rootLogger)
|
||||
governorCtrl := governor.NewController(governorService, rootLogger)
|
||||
|
||||
// Setup API
|
||||
app := fiber.New()
|
||||
// Setup app with custom error handling.
|
||||
response.SetEnableStackTrace(*cfg)
|
||||
app := fiber.New(fiber.Config{ErrorHandler: middleware.ErrorHandler})
|
||||
|
||||
// Middleware
|
||||
prometheus := fiberprometheus.New("wormscan")
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// package middleare contains all the middleware function to use in the API.
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
errs "github.com/wormhole-foundation/wormhole-explorer/api/internal/errors"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/response"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
// ErrorHandler define a fiber custom error handler. This function process all errors
|
||||
// returned from any handlers in the stack.
|
||||
//
|
||||
// To setup this function we must set the ErrorHandler field of the fiber.Config struct
|
||||
// with this function and create a new fiber with this config.
|
||||
//
|
||||
// example: fiber.New(fiber.Config{ErrorHandler: errs.APIErrorHandler}
|
||||
func ErrorHandler(ctx *fiber.Ctx, err error) error {
|
||||
var apiError response.APIError
|
||||
switch {
|
||||
case errors.As(err, &apiError):
|
||||
ctx.Status(apiError.StatusCode).JSON(apiError)
|
||||
case errors.Is(err, errs.ErrNotFound):
|
||||
apiError = response.NewNotFoundError(ctx)
|
||||
ctx.Status(fiber.StatusNotFound).JSON(apiError)
|
||||
default:
|
||||
apiError = response.NewInternalError(ctx, err)
|
||||
ctx.Status(fiber.StatusInternalServerError).JSON(apiError)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,15 +1,50 @@
|
|||
// package middleare contains all the middleware function to use in the API.
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/pagination"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/pagination"
|
||||
)
|
||||
|
||||
// ExtractPagination middleware invoke pagination.ExtractPagination.
|
||||
func ExtractPagination(c *fiber.Ctx) error {
|
||||
if c.Method() != http.MethodGet {
|
||||
return c.Next()
|
||||
}
|
||||
pagination.ExtractPagination(c)
|
||||
extractPagination(c)
|
||||
return c.Next()
|
||||
}
|
||||
|
||||
// extractPagination get pagination query params and build a *Pagination.
|
||||
func extractPagination(ctx *fiber.Ctx) (*pagination.Pagination, error) {
|
||||
pageNumberStr := ctx.Query("page", "0")
|
||||
pageNumber, err := strconv.ParseInt(pageNumberStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pageSizeStr := ctx.Query("pageSize", "50")
|
||||
pageSize, err := strconv.ParseInt(pageSizeStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sortOrder := ctx.Query("sortOrder", "DESC")
|
||||
sortBy := ctx.Query("sortBy", "indexedAt")
|
||||
|
||||
p := pagination.BuildPagination(pageNumber, pageSize, sortOrder, sortBy)
|
||||
ctx.Locals("pagination", p)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// GetPaginationFromContext get pagination from context.
|
||||
func GetPaginationFromContext(ctx *fiber.Ctx) *pagination.Pagination {
|
||||
p := ctx.Locals("pagination")
|
||||
if p == nil {
|
||||
return nil
|
||||
}
|
||||
return p.(*pagination.Pagination)
|
||||
}
|
||||
|
|
|
@ -1,67 +1,114 @@
|
|||
// package middleare contains all the middleware function to use in the API.
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/vaa"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/response"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrMalformedChain = errors.New("WRONG_CHAIN_ID")
|
||||
ErrMalformedAddr = errors.New("MALFORMED_EMITTER_ADDR")
|
||||
ErrMalformedSequence = errors.New("MALFORMED_SEQUENCE_NUMBER")
|
||||
ErrMalFormedGuardianAddress = errors.New("MALFORMED_GUARDIAN_ADDR")
|
||||
)
|
||||
|
||||
func ExtractChainID(c *fiber.Ctx) (vaa.ChainID, error) {
|
||||
// ExtractChainID get chain parameter from route path.
|
||||
func ExtractChainID(c *fiber.Ctx, l *zap.Logger) (vaa.ChainID, error) {
|
||||
chain, err := c.ParamsInt("chain")
|
||||
if err != nil {
|
||||
return vaa.ChainIDUnset, ErrMalformedChain
|
||||
requestID := fmt.Sprintf("%v", c.Locals("requestid"))
|
||||
l.Error("failed to get chain parameter", zap.Error(err), zap.Int("chain", chain),
|
||||
zap.String("requestID", requestID))
|
||||
|
||||
return vaa.ChainIDUnset, response.NewInvalidParamError(c, "WRONG CHAIN ID", errors.WithStack(err))
|
||||
}
|
||||
return vaa.ChainID(chain), nil
|
||||
}
|
||||
|
||||
func ExtractEmitterAddr(c *fiber.Ctx) (*vaa.Address, error) {
|
||||
// ExtractEmitterAddr get emitter parameter from route path.
|
||||
func ExtractEmitterAddr(c *fiber.Ctx, l *zap.Logger) (*vaa.Address, error) {
|
||||
emitterStr := c.Params("emitter")
|
||||
emitter, err := vaa.StringToAddress(emitterStr)
|
||||
if err != nil {
|
||||
return nil, ErrMalformedAddr
|
||||
requestID := fmt.Sprintf("%v", c.Locals("requestid"))
|
||||
l.Error("failed to covert emitter to address", zap.Error(err), zap.String("emitterStr", emitterStr),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, response.NewInvalidParamError(c, "MALFORMED EMITTER_ADDR", errors.WithStack(err))
|
||||
}
|
||||
return &emitter, nil
|
||||
}
|
||||
|
||||
func ExtractSequence(c *fiber.Ctx) (uint64, error) {
|
||||
// ExtractSequence get sequence parameter from route path.
|
||||
func ExtractSequence(c *fiber.Ctx, l *zap.Logger) (uint64, error) {
|
||||
sequence := c.Params("sequence")
|
||||
seq, err := strconv.ParseUint(sequence, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
requestID := fmt.Sprintf("%v", c.Locals("requestid"))
|
||||
l.Error("failed to get sequence parameter", zap.Error(err), zap.String("sequence", sequence),
|
||||
zap.String("requestID", requestID))
|
||||
return 0, response.NewInvalidParamError(c, "MALFORMED SEQUENCE NUMBER", errors.WithStack(err))
|
||||
}
|
||||
return seq, nil
|
||||
}
|
||||
|
||||
func ExtractGuardianAddress(c *fiber.Ctx) (string, error) {
|
||||
// ExtractGuardianAddress get guardian address from route path.
|
||||
func ExtractGuardianAddress(c *fiber.Ctx, l *zap.Logger) (string, error) {
|
||||
//TODO: check guardianAddress [vaa.StringToAddress(emitterStr)]
|
||||
guardianAddress := c.Params("guardian_address")
|
||||
if guardianAddress == "" {
|
||||
return "", ErrMalFormedGuardianAddress
|
||||
return "", response.NewInvalidParamError(c, "MALFORMED GUARDIAN ADDR", nil)
|
||||
}
|
||||
return guardianAddress, nil
|
||||
}
|
||||
|
||||
func ExtractVAAParams(c *fiber.Ctx) (vaa.ChainID, *vaa.Address, uint64, error) {
|
||||
chainID, err := ExtractChainID(c)
|
||||
// ExtractVAAParams get VAA chain, address from route path.
|
||||
func ExtractVAAChainIDEmitter(c *fiber.Ctx, l *zap.Logger) (vaa.ChainID, *vaa.Address, error) {
|
||||
chainID, err := ExtractChainID(c, l)
|
||||
if err != nil {
|
||||
return vaa.ChainIDUnset, nil, err
|
||||
}
|
||||
address, err := ExtractEmitterAddr(c, l)
|
||||
if err != nil {
|
||||
return chainID, nil, err
|
||||
}
|
||||
return chainID, address, nil
|
||||
}
|
||||
|
||||
// ExtractVAAParams get VAAA chain, address and sequence from route path.
|
||||
func ExtractVAAParams(c *fiber.Ctx, l *zap.Logger) (vaa.ChainID, *vaa.Address, uint64, error) {
|
||||
chainID, err := ExtractChainID(c, l)
|
||||
if err != nil {
|
||||
return vaa.ChainIDUnset, nil, 0, err
|
||||
}
|
||||
address, err := ExtractEmitterAddr(c)
|
||||
address, err := ExtractEmitterAddr(c, l)
|
||||
if err != nil {
|
||||
return chainID, nil, 0, err
|
||||
}
|
||||
seq, err := ExtractSequence(c)
|
||||
seq, err := ExtractSequence(c, l)
|
||||
if err != nil {
|
||||
return chainID, address, 0, err
|
||||
}
|
||||
return chainID, address, seq, nil
|
||||
}
|
||||
|
||||
// ExtractObservationSigner get signer from route path.
|
||||
func ExtractObservationSigner(c *fiber.Ctx, l *zap.Logger) (*vaa.Address, error) {
|
||||
signer := c.Params("signer")
|
||||
signerAddr, err := vaa.StringToAddress(signer)
|
||||
if err != nil {
|
||||
requestID := fmt.Sprintf("%v", c.Locals("requestid"))
|
||||
l.Error("failed to covert signer to address", zap.Error(err), zap.String("signer", signer),
|
||||
zap.String("requestID", requestID))
|
||||
return nil, response.NewInvalidParamError(c, "MALFORMED SIGNER", errors.WithStack(err))
|
||||
}
|
||||
return &signerAddr, nil
|
||||
}
|
||||
|
||||
// ExtractObservationHash get a hash from route path.
|
||||
func ExtractObservationHash(c *fiber.Ctx, l *zap.Logger) (string, error) {
|
||||
hash := c.Params("hash")
|
||||
if hash == "" {
|
||||
return "", response.NewInvalidParamError(c, "MALFORMED HASH", nil)
|
||||
}
|
||||
return hash, nil
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
package pagination
|
||||
|
||||
import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func ExtractPagination(ctx *fiber.Ctx) (*Pagination, error) {
|
||||
pageNumberStr := ctx.Query("page", "0")
|
||||
pageNumber, err := strconv.ParseInt(pageNumberStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pageSizeStr := ctx.Query("pageSize", "50")
|
||||
pageSize, err := strconv.ParseInt(pageSizeStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sortOrder := ctx.Query("sortOrder", "DESC")
|
||||
sortBy := ctx.Query("sortBy", "indexedAt")
|
||||
|
||||
p := BuildPagination(pageNumber, pageSize, sortOrder, sortBy)
|
||||
ctx.Locals("pagination", p)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func GetFromContext(ctx *fiber.Ctx) *Pagination {
|
||||
p := ctx.Locals("pagination")
|
||||
if p == nil {
|
||||
return nil
|
||||
}
|
||||
return p.(*Pagination)
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
// The response package defines the success and error response type.
|
||||
// It define a type [AppError] that represent the api error response.
|
||||
// Its define a custom error handling for the api.
|
||||
package response
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/wormhole-foundation/wormhole-explorer/api/internal/config"
|
||||
)
|
||||
|
||||
// API error codes. These error code are the same used in guardian API.
|
||||
const (
|
||||
InvalidParam = 3
|
||||
NotFound = 5
|
||||
Internal = 13
|
||||
)
|
||||
|
||||
var enableStackTrace bool
|
||||
|
||||
// SetEnableStackTrace enable/disable send the stacktrace field in the response.
|
||||
func SetEnableStackTrace(cfg config.AppConfig) {
|
||||
if cfg.RunMode == config.RunModeDevelopmernt {
|
||||
enableStackTrace = true
|
||||
return
|
||||
}
|
||||
enableStackTrace = false
|
||||
}
|
||||
|
||||
// APIError api error response.
|
||||
// This structure is defined to be aligned with the way the guardian API handles the error response.
|
||||
type APIError struct {
|
||||
StatusCode int `json:"-"`
|
||||
Code int `json:"code"` // support to guardian-api code.
|
||||
Message string `json:"message"`
|
||||
Details []ErrorDetail `json:"details"`
|
||||
}
|
||||
|
||||
// ErrorDetail definition.
|
||||
// This structure contains the requestID and the stacktrace of the error.
|
||||
type ErrorDetail struct {
|
||||
RequestID string `json:"request_id"`
|
||||
StackTrace string `json:"stack_trace,omitempty"`
|
||||
}
|
||||
|
||||
// Error interface implementation.
|
||||
func (a APIError) Error() string {
|
||||
return fmt.Sprintf("code: %d, message: %s, details: %v", a.Code, a.Message, a.Details)
|
||||
}
|
||||
|
||||
// NewApiError create a new api response.
|
||||
func NewApiError(ctx *fiber.Ctx, statusCode, code int, message string, err error) APIError {
|
||||
detail := ErrorDetail{
|
||||
RequestID: fmt.Sprintf("%v", ctx.Locals("requestid")),
|
||||
}
|
||||
if enableStackTrace && err != nil {
|
||||
detail.StackTrace = fmt.Sprintf("%+v\n", err)
|
||||
}
|
||||
return APIError{
|
||||
StatusCode: fiber.StatusBadRequest,
|
||||
Code: InvalidParam,
|
||||
Message: message,
|
||||
Details: []ErrorDetail{detail},
|
||||
}
|
||||
}
|
||||
|
||||
// NewInvalidParamError create a invalid param Error.
|
||||
func NewInvalidParamError(ctx *fiber.Ctx, message string, err error) APIError {
|
||||
if message == "" {
|
||||
message = "INVALID PARAM"
|
||||
}
|
||||
detail := ErrorDetail{
|
||||
RequestID: fmt.Sprintf("%v", ctx.Locals("requestid")),
|
||||
}
|
||||
if enableStackTrace && err != nil {
|
||||
detail.StackTrace = fmt.Sprintf("%+v\n", err)
|
||||
}
|
||||
return APIError{
|
||||
StatusCode: fiber.StatusBadRequest,
|
||||
Code: InvalidParam,
|
||||
Message: message,
|
||||
Details: []ErrorDetail{detail},
|
||||
}
|
||||
}
|
||||
|
||||
// NewInternalError create a new APIError for Internal Errors.
|
||||
func NewInternalError(ctx *fiber.Ctx, err error) APIError {
|
||||
detail := ErrorDetail{
|
||||
RequestID: fmt.Sprintf("%v", ctx.Locals("requestid")),
|
||||
}
|
||||
if enableStackTrace && err != nil {
|
||||
detail.StackTrace = fmt.Sprintf("%+v\n", err)
|
||||
}
|
||||
return APIError{
|
||||
StatusCode: fiber.StatusInternalServerError,
|
||||
Code: Internal,
|
||||
Message: "INTERNAL ERROR",
|
||||
Details: []ErrorDetail{detail},
|
||||
}
|
||||
}
|
||||
|
||||
// NewNotFoundError create a new APIError for Not Found errors.
|
||||
func NewNotFoundError(ctx *fiber.Ctx) APIError {
|
||||
return APIError{
|
||||
StatusCode: fiber.StatusNotFound,
|
||||
Code: NotFound,
|
||||
Message: "NOT FOUND",
|
||||
Details: []ErrorDetail{{
|
||||
RequestID: fmt.Sprintf("%v", ctx.Locals("requestid")),
|
||||
}},
|
||||
}
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
package services
|
||||
// The response package defines the success and error response type.
|
||||
package response
|
||||
|
||||
// ResponsePagination definition.
|
||||
type ResponsePagination struct {
|
||||
Next string `json:"next"`
|
||||
}
|
||||
|
||||
// Response represent a success API response.
|
||||
type Response[T any] struct {
|
||||
Data T `json:"data"`
|
||||
Error error `json:"error"`
|
||||
Pagination ResponsePagination `json:"pagination"`
|
||||
}
|
Loading…
Reference in New Issue