diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 6e05c6e..af56aac 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -21,10 +21,7 @@ jobs: with: go-version-file: 'go.mod' - - name: Install golangci-lint - run: | - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin - echo "$(go env GOPATH)/bin" >> $GITHUB_PATH - - - name: Run make lint - run: make lint + - name: Run golangci-lint + uses: golangci/golangci-lint-action@v8 + with: + version: latest diff --git a/README.md b/README.md index 3bbe6f0..f2ee322 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ Metrics will be available at `http://localhost:2112/metrics` - `--evm-ws-url`: EVM client WebSocket URL (default: `ws://localhost:8546`) - `--evm-rpc-url`: EVM client JSON-RPC URL for health checks (optional, enables JSON-RPC monitoring) - `--celestia-url`: Celestia DA JSON-RPC URL (default: `http://localhost:26658`) -- `--celestia-token`: Celestia authentication token (optional) +- `--celestia-token`: Celestia authentication token (optional), sent as a `Bearer` token on all Celestia requests, including block timestamp lookups. Required when the celestia-node has auth enabled (the default). - `--duration`: Duration in seconds to stream (0 = infinite) - `--chain-id`: Chain identifier for metrics labels (default: "testnet") - `--enable-metrics`: Enable Prometheus metrics HTTP server (default: false) diff --git a/internal/clients/celestia/client.go b/internal/clients/celestia/client.go index b4d281d..e3bd7d3 100644 --- a/internal/clients/celestia/client.go +++ b/internal/clients/celestia/client.go @@ -22,6 +22,7 @@ type Client struct { *jsonrpc.Client logger zerolog.Logger url string + token string } func NewClient(ctx context.Context, url, token string, logger zerolog.Logger) (*Client, error) { @@ -35,6 +36,7 @@ func NewClient(ctx context.Context, url, token string, logger zerolog.Logger) (* Client: client, logger: logger.With().Str("component", "celestia_client").Logger(), url: url, + token: token, }, nil } @@ -245,6 +247,9 @@ func (c *Client) GetBlockTimestamp(ctx context.Context, daHeight uint64) (time.T return time.Time{}, fmt.Errorf("failed to create request: %w", err) } req.Header.Set("Content-Type", "application/json") + if c.token != "" { + req.Header.Set("Authorization", "Bearer "+c.token) + } resp, err := http.DefaultClient.Do(req) if err != nil { diff --git a/internal/clients/celestia/client_test.go b/internal/clients/celestia/client_test.go new file mode 100644 index 0000000..ae82180 --- /dev/null +++ b/internal/clients/celestia/client_test.go @@ -0,0 +1,44 @@ +package celestia + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/rs/zerolog" + "github.com/stretchr/testify/require" +) + +func TestGetBlockTimestamp_AuthorizationHeader(t *testing.T) { + tests := []struct { + name string + token string + wantHeader string + wantSet bool + }{ + {name: "token configured", token: "secret", wantHeader: "Bearer secret", wantSet: true}, + {name: "no token", token: ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var gotHeader []string + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + gotHeader = r.Header.Values("Authorization") + _, _ = w.Write([]byte(`{"result":{"header":{"time":"2024-01-02T03:04:05Z"}}}`)) + })) + defer srv.Close() + + c := &Client{logger: zerolog.Nop(), url: srv.URL, token: tt.token} + _, err := c.GetBlockTimestamp(context.Background(), 1) + require.NoError(t, err) + + if tt.wantSet { + require.Equal(t, []string{tt.wantHeader}, gotHeader) + } else { + require.Empty(t, gotHeader) + } + }) + } +}