Overview
Go is a statically-typed, compiled language known for its simplicity, efficiency, and strong concurrency support. Follow the official installation guide to install Go. Verify the installation:
go version
Authentication for Go Requests
To securely access Hyperliquid gRPC, authentication is required. Quicknode endpoints consist of two components: endpoint name and token. You must use these components to configure a gRPC client with authentication credentials.
There are two authentication methods:
- Basic Authentication
- x-token Authentication
This document provides implementation details for both methods, though x-token authentication is the recommended approach.
Basic Authentication
The getClientWithBasicAuth function demonstrates how to handle authentication using Basic Authentication. It encodes the credentials in base64 and adds them to the authorization header.
Implementation
import (
"context"
"crypto/tls"
"encoding/base64"
"fmt"
"log"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
func getClientWithBasicAuth(endpoint, token string) (*grpc.ClientConn, error) {
target := endpoint + ":10000"
conn, err := grpc.Dial(target,
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})),
grpc.WithPerRPCCredentials(basicAuth{
username: endpoint,
password: token,
}),
)
if err != nil {
return nil, fmt.Errorf("unable to dial endpoint: %w", err)
}
return conn, nil
}
type basicAuth struct {
username string
password string
}
func (b basicAuth) GetRequestMetadata(ctx context.Context, in ...string) (map[string]string, error) {
auth := b.username + ":" + b.password
encoded := base64.StdEncoding.EncodeToString([]byte(auth))
return map[string]string{"authorization": "Basic " + encoded}, nil
}
func (basicAuth) RequireTransportSecurity() bool {
return true
}
Usage
conn, err := getClientWithBasicAuth("ENDPOINT_NAME", "TOKEN")
if err != nil {
log.Fatalf("failed to connect: %v", err)
}
defer conn.Close()
x-token Authentication
The getClientWithXToken function demonstrates how to authenticate using an x-token. This method attaches the token to the x-token header of each request.
Implementation
import (
"context"
"crypto/tls"
"fmt"
"log"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
func getClientWithXToken(endpoint, token string) (*grpc.ClientConn, error) {
target := endpoint + ":10000"
conn, err := grpc.Dial(target,
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})),
grpc.WithPerRPCCredentials(xTokenAuth{
token: token,
}),
)
if err != nil {
return nil, fmt.Errorf("unable to dial endpoint: %w", err)
}
return conn, nil
}
type xTokenAuth struct {
token string
}
func (x xTokenAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
return map[string]string{"x-token": x.token}, nil
}
func (xTokenAuth) RequireTransportSecurity() bool {
return true
}
Usage
conn, err := getClientWithXToken("ENDPOINT_NAME", "TOKEN")
if err != nil {
log.Fatalf("failed to connect: %v", err)
}
defer conn.Close()
Initiating the Go Project for Hyperliquid gRPC
Step 1: Initialize Go Project
Create a dedicated directory for your Hyperliquid gRPC project and navigate into it:
mkdir hyperliquid-grpc-go
cd hyperliquid-grpc-go
go mod init hyperliquid-grpc-go
Step 2: Install Dependencies
Install the necessary Go dependencies for gRPC and Protocol Buffers:
# Install gRPC and Protocol Buffers packages
go get google.golang.org/grpc
go get google.golang.org/protobuf/cmd/protoc-gen-go
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc
# Make sure the protoc plugins are in your PATH
export PATH="$PATH:$(go env GOPATH)/bin"
Step 3: Create Proto Files
Create the proto directory and add the Hyperliquid streaming protocol definition:
# Create proto directory
mkdir -p proto
Create a new file named streaming.proto in the proto/ directory and add the following content:
syntax = "proto3";
package hyperliquid;
service Streaming {
// Bi-directional streaming
rpc StreamData (stream SubscribeRequest) returns (stream SubscribeUpdate);
rpc Ping (PingRequest) returns (PingResponse);
}
service BlockStreaming {
// Stream replica_cmds (raw blocks)
rpc StreamBlocks (Timestamp) returns (stream Block);
}
// --- Requests ---
message SubscribeRequest {
oneof request {
StreamSubscribe subscribe = 1;
Ping ping = 3;
}
reserved 2;
}
message StreamSubscribe {
StreamType stream_type = 1;
uint64 start_block = 2;
// Generic filters - field name to allowed values
// Recursively searches each event for matching field/value pairs
// Example: {"coin": ["ETH", "BTC"], "user": ["0x123..."], "type": ["deposit"]}
map<string, FilterValues> filters = 3;
// Optional name for this filter
// Allows multiple independent filters per stream (OR logic)
string filter_name = 4;
}
// Container for filter values
message FilterValues {
repeated string values = 1;
}
message Ping { int64 timestamp = 1; }
// --- Responses ---
message SubscribeUpdate {
oneof update {
StreamResponse data = 1;
Pong pong = 2;
}
}
message StreamResponse {
uint64 block_number = 1;
uint64 timestamp = 2; // Server ingress timestamp
// Raw JSON data from the file (Exact replica of source)
string data = 3;
}
// --- Data Types ---
enum StreamType {
UNKNOWN = 0;
TRADES = 1;
ORDERS = 2;
BOOK_UPDATES = 3;
TWAP = 4;
EVENTS = 5;
BLOCKS = 6;
WRITER_ACTIONS = 7;
}
message Block {
string data_json = 1;
}
message Pong { int64 timestamp = 1; }
message Timestamp { int64 timestamp = 1; }
message PingRequest { int32 count = 1; }
message PingResponse { int32 count = 1; }
Step 4: Generate Go Code from Proto Files
Generate Go client code from the protocol buffer definition:
# Create pb directory for generated files
mkdir -p pb
# Generate Go code from proto files
protoc --go_out=pb --go_opt=paths=source_relative \
--go-grpc_out=pb --go-grpc_opt=paths=source_relative \
proto/*.proto
Step 5: Create Main Application
Create your main application file to test the connection:
package main
import (
"context"
"crypto/tls"
"fmt"
"log"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
pb "hyperliquid-grpc-go/pb/proto"
)
const (
grpcEndpoint = "your-grpc-endpoint:port"
authToken = "your-auth-token"
)
// Create gRPC connection with TLS
func createConnection() (*grpc.ClientConn, error) {
tlsConfig := &tls.Config{
InsecureSkipVerify: false,
}
creds := credentials.NewTLS(tlsConfig)
conn, err := grpc.Dial(
grpcEndpoint,
grpc.WithTransportCredentials(creds),
grpc.WithDefaultCallOptions(
grpc.MaxCallRecvMsgSize(100*1024*1024), // 100MB
),
)
return conn, err
}
// Create context with auth metadata
func createContext() context.Context {
md := metadata.Pairs("x-token", authToken)
return metadata.NewOutgoingContext(context.Background(), md)
}
// Test connectivity
func pingTest(client pb.StreamingClient) error {
ctx := createContext()
resp, err := client.Ping(ctx, &pb.PingRequest{Count: 1})
if err != nil {
return fmt.Errorf("ping failed: %v", err)
}
log.Printf("✅ Ping successful: %+v", resp)
return nil
}
func main() {
// Create connection
conn, err := createConnection()
if err != nil {
log.Fatalf("❌ Failed to connect: %v", err)
}
defer conn.Close()
// Create client
client := pb.NewStreamingClient(conn)
// Test connectivity
fmt.Printf("Testing connection to: %s\n", grpcEndpoint)
if err := pingTest(client); err != nil {
log.Fatalf("❌ Ping test failed: %v", err)
}
fmt.Println("✅ Connection test completed successfully!")
}
Step 6: Run the Application
Build and execute your application to test the gRPC connection:
# Download and update dependencies
go mod tidy
# Build and run
go build -o hyperliquid-grpc main.go
./hyperliquid-grpc
# Or run directly
go run main.go
Step 7: Verify Setup
Confirm that your setup is working correctly by checking the output, it should be something like below:
Testing connection to: docs-demo.hype-mainnet.quiknode.pro:10000
2025/12/30 18:10:52 ✅ Ping successful: count:1
✅ Connection test completed successfully!
If everything is set up correctly, you should see:
- Connection established to the gRPC endpoint
- Successful ping response
- No compilation or runtime errors
We ❤️ Feedback!
If you have any feedback or questions about this documentation, let us know. We'd love to hear from you!