The GetNewBlockStream
stream provides low-latency access to new blocks as they’re produced on the Base network. Note that there is a low chance that this stream may include blocks that will not be accepted on chain.
This is a real-time gRPC stream delivering full block headers and bodies (including transactions), intended for searchers, indexers, and other latency-sensitive applications.
Quickstart
Prerequisites
op-geth
installed (pay attention to use it instread of go-ethereum
)
gRPC installed (google.golang.org/grpc
)
gRPC Endpoint
Copy base.blxrbdn.com:8080
Authorization required via authorization
header
Authentication
Set your authorization header via environment variable:
Copy export AUTH_HEADER="<your-auth-header>"
In gRPC, this will be passed as:
Copy metadata.New(map[string]string{
"authorization": os.Getenv("AUTH_HEADER"),
})
Example: Test with grpcurl
Copy grpcurl -plaintext -H "authorization: <auth-header>" \
-d '{}' \
base.blxrbdn.com:8080 \
streamer_api.Streamer/GetNewBlockStream
This will return raw stream data — you can pretty-print it with jq
.
GO Example: Listen for New Blocks on Base
🔗 You can get the .proto
file here
🔗 You can access the Base streamer client here
Copy package examples
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/bloXroute-Labs/base-streamer-client-go/provider"
streamerapi "github.com/bloXroute-Labs/base-streamer-proto/streamer_api"
"github.com/ethereum/go-ethereum/core/types"
)
func ListenForNewBlocks(numberOfBlocks uint64) error {
grpcClient, err := provider.NewGRPCClient()
if err != nil {
return err
}
blocksChan := make(chan *streamerapi.GetNewBlockStreamResponse)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
stream, err := grpcClient.GetNewBlockStream(ctx)
if err != nil {
return fmt.Errorf("failed to get stream with: %v", err)
}
stream.Into(blocksChan)
fmt.Println("waiting on blocks channel")
for range numberOfBlocks {
newBlock, ok := <-blocksChan
if !ok {
// channel closed
return fmt.Errorf("new blocks channel closed")
}
updateTime := time.Now()
blockHeader := &types.Header{}
err := blockHeader.UnmarshalJSON(newBlock.BlockHeader)
if err != nil {
return fmt.Errorf("failed to unmarshal block header with: %v", err)
}
var blockBody *types.Body
err = json.Unmarshal(newBlock.BlockBody, &blockBody)
if err != nil {
return fmt.Errorf("failed to unmarshal block body with: %v", err)
}
fmt.Printf("new block: %v, %v txns at %v\n", blockHeader.Number.Uint64(), len(blockBody.Transactions), updateTime.UTC())
}
return nil
}
Sample output:
Copy waiting on blocks channel
new block: 12345678, 120 txns at 2025-03-25 12:45:01.234 UTC
new block: 12345679, 98 txns at 2025-03-25 12:45:13.147 UTC
...
Troubleshooting
Stream closes unexpectedly
Expired token, gRPC connection limits, network/firewall issues
Mismatched Go or op-geth
dependency
Ensure proper env variables and endpoint configuration