diff --git a/.gitignore b/.gitignore index 6fe7bb1..80b8f5a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ go.work rabbitmq_data + +.vscode \ No newline at end of file diff --git a/cmd/babylon-staking-indexer/main.go b/cmd/babylon-staking-indexer/main.go index 5155a55..772546f 100644 --- a/cmd/babylon-staking-indexer/main.go +++ b/cmd/babylon-staking-indexer/main.go @@ -8,7 +8,8 @@ import ( "github.com/rs/zerolog/log" "github.com/babylonlabs-io/babylon-staking-indexer/cmd/babylon-staking-indexer/cli" - "github.com/babylonlabs-io/babylon-staking-indexer/internal/client/btcclient" + "github.com/babylonlabs-io/babylon-staking-indexer/internal/clients/bbnclient" + "github.com/babylonlabs-io/babylon-staking-indexer/internal/clients/btcclient" "github.com/babylonlabs-io/babylon-staking-indexer/internal/config" "github.com/babylonlabs-io/babylon-staking-indexer/internal/db" "github.com/babylonlabs-io/babylon-staking-indexer/internal/observability/metrics" @@ -47,13 +48,14 @@ func main() { if err != nil { log.Fatal().Err(err).Msg("error while creating btc client") } + bbnClient := bbnclient.NewBbnClient(&cfg.Bbn) qm, err := queue.NewQueueManager(&cfg.Queue) if err != nil { log.Fatal().Err(err).Msg("error while creating queue manager") } - service := services.NewService(dbClient, btcClient, qm) + service := services.NewService(dbClient, btcClient, bbnClient, qm) if err != nil { log.Fatal().Err(err).Msg("error while creating delegation service") } diff --git a/config/config-docker.yml b/config/config-docker.yml index 3b5f133..83a2c28 100644 --- a/config/config-docker.yml +++ b/config/config-docker.yml @@ -12,6 +12,10 @@ btc: net-params: testnet rpc-user: rpcuser rpc-pass: rpcpass +bbn: + endpoint: localhost + port: 443 + timeout: 10000 # 10 seconds queue: queue_user: user # can be replaced by values in .env file queue_password: password diff --git a/config/config-local.yml b/config/config-local.yml index 3691069..63d80f8 100644 --- a/config/config-local.yml +++ b/config/config-local.yml @@ -12,6 +12,10 @@ btc: net-params: testnet rpc-user: rpcuser rpc-pass: rpcpass +bbn: + endpoint: rpc.devnet.babylonchain.io + port: 443 + timeout: 10000 # 10 seconds queue: queue_user: user # can be replaced by values in .env file queue_password: password diff --git a/go.mod b/go.mod index c2af646..f89b56f 100644 --- a/go.mod +++ b/go.mod @@ -4,38 +4,54 @@ go 1.23.2 require ( github.com/babylonlabs-io/staking-queue-client v0.4.1 - github.com/btcsuite/btcd v0.24.0 + github.com/btcsuite/btcd v0.24.2 github.com/go-chi/chi/v5 v5.1.0 - github.com/spf13/viper v1.18.2 + github.com/spf13/viper v1.19.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect - github.com/btcsuite/btcd/btcutil v1.1.5 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect + github.com/btcsuite/btcd/btcutil v1.1.6 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cometbft/cometbft v0.38.12 // indirect + github.com/cosmos/gogoproto v1.7.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect - github.com/golang/snappy v0.0.4 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/klauspost/compress v1.17.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae // indirect + github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.48.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/sync v0.5.0 // indirect - google.golang.org/protobuf v1.32.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sync v0.8.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect + google.golang.org/grpc v1.62.1 // indirect + google.golang.org/protobuf v1.34.2 // indirect ) require ( @@ -44,25 +60,25 @@ require ( github.com/joho/godotenv v1.5.1 github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/prometheus/client_golang v1.19.0 + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/prometheus/client_golang v1.20.1 github.com/rs/zerolog v1.32.0 github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.9.0 github.com/subosito/gotenv v1.6.0 // indirect go.mongodb.org/mongo-driver v1.14.0 go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/sys v0.16.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/text v0.17.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 2e46ddc..f59ed4a 100644 --- a/go.sum +++ b/go.sum @@ -6,15 +6,17 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= -github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= -github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= -github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/btcutil v1.1.6 h1:zFL2+c3Lb9gEgqKNzowKUPQNb8jV7v5Oaodi/AYFd6c= +github.com/btcsuite/btcd/btcutil v1.1.6/go.mod h1:9dFymx8HpuLqBnsPELrImQeTQfKBQqzqGbbV3jK55aE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= @@ -31,19 +33,25 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cometbft/cometbft v0.38.12 h1:OWsLZN2KcSSFe8bet9xCn07VwhBnavPea3VyPnNq1bg= +github.com/cometbft/cometbft v0.38.12/go.mod h1:GPHp3/pehPqgX1930HmK1BpBLZPxB75v/dZg8Viwy+o= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cosmos/gogoproto v1.7.0 h1:79USr0oyXAbxg3rspGh/m4SWNyoz/GLaAh0QlCe2fro= +github.com/cosmos/gogoproto v1.7.0/go.mod h1:yWChEv5IUEYURQasfyBW5ffkMHR/90hiHgbNgrtp4j0= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= @@ -53,6 +61,10 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= @@ -61,15 +73,19 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -81,24 +97,31 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae h1:FatpGJD2jmJfhZiFDElaC0QhZUDQnxUeAwTGkfAHN3I= +github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= @@ -107,22 +130,25 @@ github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= -github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/prometheus/client_golang v1.20.1 h1:IMJXHOD6eARkQpxo8KkhgEVFlBNm+nkrFUyGlIu7Na8= +github.com/prometheus/client_golang v1.20.1/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= @@ -131,21 +157,24 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= +github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -172,10 +201,10 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= +golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -185,11 +214,13 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -206,8 +237,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -215,22 +246,27 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c h1:lfpJ/2rWPa/kJgxyyXM8PrNnfCzcmxJ265mADgwmvLI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= +google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/clients/base/base_client.go b/internal/clients/base/base_client.go new file mode 100644 index 0000000..8088561 --- /dev/null +++ b/internal/clients/base/base_client.go @@ -0,0 +1,138 @@ +package baseclient + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + "time" + + "github.com/babylonlabs-io/babylon-staking-indexer/internal/observability/metrics" + "github.com/babylonlabs-io/babylon-staking-indexer/internal/types" + "github.com/rs/zerolog/log" +) + +var ALLOWED_METHODS = []string{"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"} + +type BaseClient interface { + GetBaseURL() string + GetDefaultRequestTimeout() int + GetHttpClient() *http.Client +} + +type BaseClientOptions struct { + Timeout int + Path string + TemplatePath string // Metrics purpose + Headers map[string]string +} + +func isAllowedMethod(method string) bool { + for _, allowedMethod := range ALLOWED_METHODS { + if method == allowedMethod { + return true + } + } + return false +} + +func sendRequest[I any, R any]( + ctx context.Context, client BaseClient, method string, opts *BaseClientOptions, input *I, +) (*R, *types.Error) { + if !isAllowedMethod(method) { + return nil, types.NewInternalServiceError(fmt.Errorf("method %s is not allowed", method)) + } + url := fmt.Sprintf("%s%s", client.GetBaseURL(), opts.Path) + timeout := client.GetDefaultRequestTimeout() + // If timeout is set, use it instead of the default + if opts.Timeout != 0 { + timeout = opts.Timeout + } + // Set a timeout for the request + ctxWithTimeout, cancel := context.WithTimeout(ctx, time.Duration(timeout)*time.Millisecond) + defer cancel() + + var req *http.Request + var requestError error + if input != nil && (method == http.MethodPost || method == http.MethodPut) { + body, err := json.Marshal(input) + if err != nil { + return nil, types.NewErrorWithMsg( + http.StatusInternalServerError, + types.InternalServiceError, + "failed to marshal request body", + ) + } + req, requestError = http.NewRequestWithContext(ctxWithTimeout, method, url, bytes.NewBuffer(body)) + } else { + req, requestError = http.NewRequestWithContext(ctxWithTimeout, method, url, nil) + } + if requestError != nil { + return nil, types.NewErrorWithMsg( + http.StatusInternalServerError, types.InternalServiceError, requestError.Error(), + ) + } + // Set headers + for key, value := range opts.Headers { + req.Header.Set(key, value) + } + + resp, err := client.GetHttpClient().Do(req) + if err != nil { + if ctx.Err() == context.DeadlineExceeded || err.Error() == "context canceled" { + return nil, types.NewErrorWithMsg( + http.StatusRequestTimeout, + types.RequestTimeout, + fmt.Sprintf("request timeout after %d ms at %s", timeout, url), + ) + } + return nil, types.NewErrorWithMsg( + http.StatusInternalServerError, + types.InternalServiceError, + fmt.Sprintf("failed to send request to %s", url), + ) + } + defer resp.Body.Close() + + if resp.StatusCode >= http.StatusInternalServerError { + return nil, types.NewErrorWithMsg( + resp.StatusCode, + types.InternalServiceError, + fmt.Sprintf("internal server error when calling %s", url), + ) + } else if resp.StatusCode >= http.StatusBadRequest { + return nil, types.NewErrorWithMsg( + resp.StatusCode, + types.BadRequest, + fmt.Sprintf("client error when calling %s", url), + ) + } + + var output R + if err := json.NewDecoder(resp.Body).Decode(&output); err != nil { + return nil, types.NewErrorWithMsg( + http.StatusInternalServerError, + types.InternalServiceError, + fmt.Sprintf("failed to decode response from %s", url), + ) + } + + return &output, nil +} + +func SendRequest[I any, R any]( + ctx context.Context, client BaseClient, method string, opts *BaseClientOptions, input *I, +) (*R, *types.Error) { + timer := metrics.StartClientRequestDurationTimer( + client.GetBaseURL(), method, opts.TemplatePath, + ) + result, err := sendRequest[I, R](ctx, client, method, opts, input) + if err != nil { + log.Ctx(ctx).Error().Err(err).Msgf("failed to send request") + timer(err.StatusCode) + return nil, err + } + timer(http.StatusOK) + return result, err +} diff --git a/internal/clients/bbnclient/bbnclient.go b/internal/clients/bbnclient/bbnclient.go new file mode 100644 index 0000000..47aa789 --- /dev/null +++ b/internal/clients/bbnclient/bbnclient.go @@ -0,0 +1,101 @@ +package bbnclient + +import ( + "context" + "fmt" + "net/http" + "strconv" + + baseclient "github.com/babylonlabs-io/babylon-staking-indexer/internal/clients/base" + "github.com/babylonlabs-io/babylon-staking-indexer/internal/clients/bbnclient/bbntypes" + "github.com/babylonlabs-io/babylon-staking-indexer/internal/config" + "github.com/babylonlabs-io/babylon-staking-indexer/internal/types" +) + +type BbnClient struct { + config *config.BbnConfig + defaultHeaders map[string]string + httpClient *http.Client +} + +func NewBbnClient(cfg *config.BbnConfig) *BbnClient { + httpClient := &http.Client{} + headers := map[string]string{ + "Content-Type": "application/json", + "Accept": "application/json", + } + return &BbnClient{ + cfg, + headers, + httpClient, + } +} + +// Necessary for the BaseClient interface +func (c *BbnClient) GetBaseURL() string { + return fmt.Sprintf("https://%s:%s", c.config.Endpoint, c.config.Port) +} + +func (c *BbnClient) GetDefaultRequestTimeout() int { + return c.config.Timeout +} + +func (c *BbnClient) GetHttpClient() *http.Client { + return c.httpClient +} + +func (c *BbnClient) GetHealthCheckStatus(ctx context.Context) (bool, *types.Error) { + path := "/health" + opts := &baseclient.BaseClientOptions{ + Path: path, + TemplatePath: path, + Headers: c.defaultHeaders, + } + + _, err := baseclient.SendRequest[any, any]( + ctx, c, http.MethodGet, opts, nil, + ) + return err == nil, err +} + +func (c *BbnClient) GetLatestBlockNumber(ctx context.Context) (int, *types.Error) { + blockResult, err := c.getBlockResults(ctx, 0) + if err != nil { + return 0, err + } + // Parse the string as an unsigned integer (base 10) + height, parseErr := strconv.Atoi(blockResult.Height) + if parseErr != nil { + return 0, types.NewErrorWithMsg( + http.StatusInternalServerError, types.InternalServiceError, parseErr.Error(), + ) + } + + return height, nil +} + +func (c *BbnClient) GetBlockResults(ctx context.Context, height int) (*bbntypes.BlockResultsResponse, *types.Error) { + return c.getBlockResults(context.Background(), height) +} + +func (c *BbnClient) getBlockResults(ctx context.Context, blockHeight int) (*bbntypes.BlockResultsResponse, *types.Error) { + path := "/block_results" + if blockHeight > 0 { + path = fmt.Sprintf("/block_results?height=%d", blockHeight) + } + opts := &baseclient.BaseClientOptions{ + Path: path, + TemplatePath: path, + Headers: c.defaultHeaders, + } + + resp, err := baseclient.SendRequest[ + any, bbntypes.CometBFTRPCResponse[bbntypes.BlockResultsResponse], + ]( + ctx, c, http.MethodGet, opts, nil, + ) + if err != nil { + return nil, err + } + return &resp.Result, nil +} diff --git a/internal/clients/bbnclient/bbntypes/types.go b/internal/clients/bbnclient/bbntypes/types.go new file mode 100644 index 0000000..3d0ce0c --- /dev/null +++ b/internal/clients/bbnclient/bbntypes/types.go @@ -0,0 +1,22 @@ +package bbntypes + +import "github.com/cometbft/cometbft/abci/types" + +// Re-exporting types.Event from cometbft package +type Event = types.Event + +type CometBFTRPCResponse[T any] struct { + Jsonrpc string `json:"jsonrpc"` + ID int `json:"id"` + Result T `json:"result"` +} + +type TransactionResult struct { + Events []types.Event `json:"events"` +} + +type BlockResultsResponse struct { + Height string `json:"height"` + TxResults []TransactionResult `json:"tx_results,omitempty"` + FinalizeBlockEvents []types.Event `json:"finalize_block_events,omitempty"` +} diff --git a/internal/clients/bbnclient/interface.go b/internal/clients/bbnclient/interface.go new file mode 100644 index 0000000..cb5bbfb --- /dev/null +++ b/internal/clients/bbnclient/interface.go @@ -0,0 +1,16 @@ +package bbnclient + +import ( + "context" + + "github.com/babylonlabs-io/babylon-staking-indexer/internal/clients/bbnclient/bbntypes" + "github.com/babylonlabs-io/babylon-staking-indexer/internal/types" +) + +type BbnInterface interface { + GetHealthCheckStatus(ctx context.Context) (bool, *types.Error) + GetLatestBlockNumber(ctx context.Context) (int, *types.Error) + GetBlockResults(ctx context.Context, height int) ( + *bbntypes.BlockResultsResponse, *types.Error, + ) +} diff --git a/internal/client/btcclient/btcclient.go b/internal/clients/btcclient/btcclient.go similarity index 100% rename from internal/client/btcclient/btcclient.go rename to internal/clients/btcclient/btcclient.go diff --git a/internal/client/btcclient/interface.go b/internal/clients/btcclient/interface.go similarity index 100% rename from internal/client/btcclient/interface.go rename to internal/clients/btcclient/interface.go diff --git a/internal/config/bbn.go b/internal/config/bbn.go new file mode 100644 index 0000000..36ceadf --- /dev/null +++ b/internal/config/bbn.go @@ -0,0 +1,26 @@ +package config + +import ( + "fmt" +) + +type BbnConfig struct { + // Endpoint specifies the URL of the BBN RPC server without the protocol prefix (http:// or https://). + Endpoint string `mapstructure:"endpoint"` + Port string `mapstructure:"port"` + Timeout int `mapstructure:"timeout"` +} + +func (cfg *BbnConfig) Validate() error { + if cfg.Endpoint == "" { + return fmt.Errorf("Babylon node endpoint is required") + } + if cfg.Port == "" { + return fmt.Errorf("Babylon node port is required") + } + if cfg.Timeout == 0 { + return fmt.Errorf("Babylon node timeout is required") + } + + return nil +} diff --git a/internal/config/config.go b/internal/config/config.go index 3800dad..0e7d7f4 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -10,18 +10,14 @@ import ( ) type Config struct { - Poller PollerConfig `mapstructure:"poller"` Db DbConfig `mapstructure:"db"` Btc BtcConfig `mapstructure:"btc"` + Bbn BbnConfig `mapstructure:"bbn"` Queue queue.QueueConfig `mapstructure:"queue"` Metrics MetricsConfig `mapstructure:"metrics"` } func (cfg *Config) Validate() error { - if err := cfg.Poller.Validate(); err != nil { - return err - } - if err := cfg.Db.Validate(); err != nil { return err } @@ -38,6 +34,10 @@ func (cfg *Config) Validate() error { return err } + if err := cfg.Bbn.Validate(); err != nil { + return err + } + return nil } diff --git a/internal/db/model/delegation.go b/internal/db/model/delegation.go index 933a915..0acd434 100644 --- a/internal/db/model/delegation.go +++ b/internal/db/model/delegation.go @@ -1,13 +1,15 @@ package model import ( + "github.com/babylonlabs-io/babylon-staking-indexer/internal/types" "go.mongodb.org/mongo-driver/bson/primitive" ) const DelegationCollection = "delegation" type DelegationDocument struct { - ID primitive.ObjectID `bson:"_id"` - StakingTxHashHex string `bson:"staking_tx_hash_hex"` - State string `bson:"state"` + ID primitive.ObjectID `bson:"_id"` + StakingTxHashHex string `bson:"staking_tx_hash_hex"` + State types.DelegationState `bson:"state"` + // TODO: Placeholder for more fields } diff --git a/internal/observability/metrics/metrics.go b/internal/observability/metrics/metrics.go index c45fceb..f6cdae7 100644 --- a/internal/observability/metrics/metrics.go +++ b/internal/observability/metrics/metrics.go @@ -28,10 +28,11 @@ func (O Outcome) String() string { } var ( - once sync.Once - metricsRouter *chi.Mux - btcClientDurationHistogram *prometheus.HistogramVec - queueSendErrorCounter prometheus.Counter + once sync.Once + metricsRouter *chi.Mux + btcClientDurationHistogram *prometheus.HistogramVec + queueSendErrorCounter prometheus.Counter + clientRequestDurationHistogram *prometheus.HistogramVec ) // Init initializes the metrics package. @@ -71,6 +72,16 @@ func initMetricsRouter(metricsPort int) { func registerMetrics() { defaultHistogramBucketsSeconds := []float64{0.1, 0.5, 1, 2.5, 5, 10, 30} + // client requests are the ones sending to other service + clientRequestDurationHistogram = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Name: "client_request_duration_seconds", + Help: "Histogram of outgoing client request durations in seconds.", + Buckets: defaultHistogramBucketsSeconds, + }, + []string{"baseurl", "method", "path", "status"}, + ) + btcClientDurationHistogram = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "btcclient_duration_seconds", @@ -91,6 +102,7 @@ func registerMetrics() { prometheus.MustRegister( btcClientDurationHistogram, queueSendErrorCounter, + clientRequestDurationHistogram, ) } @@ -117,6 +129,20 @@ func RecordBtcClientMetrics[T any](clientRequest func() (T, error)) (T, error) { return result, err } +// StartClientRequestDurationTimer starts a timer to measure outgoing client request duration. +func StartClientRequestDurationTimer(baseUrl, method, path string) func(statusCode int) { + startTime := time.Now() + return func(statusCode int) { + duration := time.Since(startTime).Seconds() + clientRequestDurationHistogram.WithLabelValues( + baseUrl, + method, + path, + fmt.Sprintf("%d", statusCode), + ).Observe(duration) + } +} + func RecordQueueSendError() { queueSendErrorCounter.Inc() } diff --git a/internal/services/bootstrap.go b/internal/services/bootstrap.go new file mode 100644 index 0000000..8d2ac74 --- /dev/null +++ b/internal/services/bootstrap.go @@ -0,0 +1,87 @@ +package services + +import ( + "context" + "time" + + "github.com/babylonlabs-io/babylon-staking-indexer/internal/clients/bbnclient/bbntypes" + "github.com/babylonlabs-io/babylon-staking-indexer/internal/types" + "github.com/rs/zerolog/log" +) + +const ( + // TODO: To be replaced by the actual starting height from the database + lastProcessedHeight = 0 + // eventProcessorSize is the size of the event processor channel + eventProcessorSize = 5000 + retryInterval = 10 * time.Second + maxRetries = 10 +) + +// bootstrapBbn handles its own retry logic and runs in a goroutine +func (s *Service) bootstrapBbn(ctx context.Context) { + go func() { + bootstrapCtx, cancel := context.WithCancel(ctx) + defer cancel() + + for retries := 0; retries < maxRetries; retries++ { + err := s.attemptBootstrap(bootstrapCtx) + if err != nil { + log.Err(err).Msgf("Failed to bootstrap BBN blockchain, attempt %d/%d", retries+1, maxRetries) + + // If the retry count reaches maxRetries, log the failure and exit + if retries == maxRetries-1 { + log.Fatal().Msg("Failed to bootstrap BBN blockchain after max retries, exiting") + } + + // Exponential backoff + time.Sleep(retryInterval * time.Duration(retries)) + } else { + log.Info().Msg("Successfully bootstrapped BBN blockchain") + break // Exit the loop if successful + } + } + }() +} + +// attemptBootstrap tries to bootstrap the blockchain, returning an error if it fails +func (s *Service) attemptBootstrap(ctx context.Context) *types.Error { + latestBbnHeight, err := s.bbn.GetLatestBlockNumber(ctx) + if err != nil { + return err + } + log.Debug().Msgf("Latest BBN block height: %d", latestBbnHeight) + + // lastProcessedHeight is already synced, so start from the next block + for i := lastProcessedHeight + 1; i <= latestBbnHeight; i++ { + events, err := s.getEventsFromBlock(ctx, i) + if err != nil { + log.Err(err).Msgf("Failed to get events from block %d", i) + return err + } + for _, event := range events { + s.eventProcessor <- event + } + } + return nil +} + +// getEventsFromBlock fetches events from a block and returns its events +func (s *Service) getEventsFromBlock(ctx context.Context, blockHeight int) ([]bbntypes.Event, *types.Error) { + events := make([]bbntypes.Event, 0) + blockResult, err := s.bbn.GetBlockResults(ctx, blockHeight) + if err != nil { + return nil, err + } + + for _, txResult := range blockResult.TxResults { + for _, event := range txResult.Events { + events = append(events, event) + } + } + for _, event := range blockResult.FinalizeBlockEvents { + events = append(events, event) + } + log.Debug().Msgf("Fetched %d events from block %d", len(events), blockHeight) + return events, nil +} diff --git a/internal/services/events.go b/internal/services/events.go new file mode 100644 index 0000000..44627b1 --- /dev/null +++ b/internal/services/events.go @@ -0,0 +1,22 @@ +package services + +import ( + "github.com/babylonlabs-io/babylon-staking-indexer/internal/clients/bbnclient/bbntypes" + "github.com/rs/zerolog/log" +) + +// startBbnEventProcessor continuously listens for events from the channel and +// processes them in the main thread +func (s *Service) startBbnEventProcessor() { + for event := range s.eventProcessor { + s.processEvent(event) + } +} + +// Entry point for processing events +func (s *Service) processEvent(event bbntypes.Event) { + switch event.Type { + case "EventBTCHeaderInserted": + log.Info().Msgf("Processing EventBTCHeaderInserted event") + } +} diff --git a/internal/services/service.go b/internal/services/service.go index a13319b..1f2f3be 100644 --- a/internal/services/service.go +++ b/internal/services/service.go @@ -3,33 +3,42 @@ package services import ( "context" - "github.com/babylonlabs-io/babylon-staking-indexer/internal/client/btcclient" + "github.com/babylonlabs-io/babylon-staking-indexer/internal/clients/bbnclient" + "github.com/babylonlabs-io/babylon-staking-indexer/internal/clients/bbnclient/bbntypes" + "github.com/babylonlabs-io/babylon-staking-indexer/internal/clients/btcclient" "github.com/babylonlabs-io/babylon-staking-indexer/internal/db" "github.com/babylonlabs-io/babylon-staking-indexer/internal/queue" ) type Service struct { - db db.DbInterface - btc btcclient.BtcInterface - queueManager *queue.QueueManager + db db.DbInterface + btc btcclient.BtcInterface + bbn bbnclient.BbnInterface + queueManager *queue.QueueManager + eventProcessor chan bbntypes.Event } -func NewService(db db.DbInterface, btc btcclient.BtcInterface, qm *queue.QueueManager) *Service { +func NewService( + db db.DbInterface, + btc btcclient.BtcInterface, + bbn bbnclient.BbnInterface, + qm *queue.QueueManager, +) *Service { + eventProcessor := make(chan bbntypes.Event, eventProcessorSize) return &Service{ - db: db, - btc: btc, - queueManager: qm, + db: db, + btc: btc, + bbn: bbn, + queueManager: qm, + eventProcessor: eventProcessor, } } -// Main entry point for the indexer service to start syncing with the blockchains -// This is a placeholder for now, we can move/restructure the location of the sync -// controller logic later func (s *Service) StartIndexerSync(ctx context.Context) { - // Step 1: Get the last processed BBN block number from the database - // Step 2: Get the latest BBN block number from the blockchain - // Step 3: Sync the blocks from the last processed block to the latest block - // Step 3.1: Call `/block_result` endpoint to get the block results - // Step 3.2: Decode the events data, feed into event processor channel (blocking) - // Step 3.3: Update the last processed block number in the database + // Start the bootstrap process + s.bootstrapBbn(ctx) + // Start the websocket event subscription process + s.subscribeToBbnEvents(ctx) + // Keep processing events in the main thread + s.startBbnEventProcessor() } diff --git a/internal/services/subscription.go b/internal/services/subscription.go new file mode 100644 index 0000000..8a010a5 --- /dev/null +++ b/internal/services/subscription.go @@ -0,0 +1,15 @@ +package services + +import "context" + +// TODO: Placeholder for subscribing to BBN events via websocket +func (s *Service) subscribeToBbnEvents(ctx context.Context) { + go func() { + for { + select { + case <-ctx.Done(): + return + } + } + }() +} diff --git a/internal/types/error.go b/internal/types/error.go index 3a21386..be4b085 100644 --- a/internal/types/error.go +++ b/internal/types/error.go @@ -17,6 +17,9 @@ const ( ValidationError ErrorCode = "VALIDATION_ERROR" NotFound ErrorCode = "NOT_FOUND" BadRequest ErrorCode = "BAD_REQUEST" + Forbidden ErrorCode = "FORBIDDEN" + UnprocessableEntity ErrorCode = "UNPROCESSABLE_ENTITY" + RequestTimeout ErrorCode = "REQUEST_TIMEOUT" ) // ApiError represents an error with an HTTP status code and an application-specific error code. diff --git a/internal/types/state.go b/internal/types/state.go new file mode 100644 index 0000000..f9c756d --- /dev/null +++ b/internal/types/state.go @@ -0,0 +1,13 @@ +package types + +// Enum values for Delegation State +type DelegationState string + +const ( + StatePending DelegationState = "PENDING" + StateActive DelegationState = "ACTIVE" + StateUnbonding DelegationState = "UNBONDING" + StateWithdrawn DelegationState = "WITHDRAWN" + StateSlashed DelegationState = "SLASHED" + StateUnbonded DelegationState = "UNBONDED" +) diff --git a/internal/poller/poller.go b/internal/utils/poller/poller.go similarity index 56% rename from internal/poller/poller.go rename to internal/utils/poller/poller.go index eda52a8..7d5c50f 100644 --- a/internal/poller/poller.go +++ b/internal/utils/poller/poller.go @@ -2,25 +2,24 @@ package poller import ( "context" + "go/types" "time" "github.com/rs/zerolog/log" - - "github.com/babylonlabs-io/babylon-staking-indexer/internal/services" ) type Poller struct { - service *services.Service - interval time.Duration - quit chan struct{} + interval time.Duration + quit chan struct{} + pollMethod func(ctx context.Context) *types.Error } -func NewPoller(interval time.Duration, service *services.Service) (*Poller, error) { +func NewPoller(interval time.Duration, pollMethod func(ctx context.Context) *types.Error) *Poller { return &Poller{ - service: service, - interval: interval, - quit: make(chan struct{}), - }, nil + interval: interval, + quit: make(chan struct{}), + pollMethod: pollMethod, + } } func (p *Poller) Start(ctx context.Context) { @@ -29,7 +28,7 @@ func (p *Poller) Start(ctx context.Context) { for { select { case <-ticker.C: - if err := p.poll(ctx); err != nil { + if err := p.pollMethod(ctx); err != nil { log.Error().Err(err).Msg("Error polling") } case <-ctx.Done(): @@ -46,7 +45,3 @@ func (p *Poller) Start(ctx context.Context) { func (p *Poller) Stop() { close(p.quit) } - -func (p *Poller) poll(ctx context.Context) error { - return nil -}