StreamL4OrderUpdates - Stream Typed Order Diffs
Maintain typed Hyperliquid resting-order state from an opening snapshot and sequenced L4 diffs over V3 gRPC.
Hyperliquid RPC endpoint: endpoint URLs, plans and pricing.
StreamL4OrderUpdates sends typed NEW, UPDATE, and REMOVE changes for the resting L4 book. Apply the diffs directly; this projection has already resolved matching effects.
Request and opening behavior
An empty coins list scopes the subscription to all coins. Explicit coins are deduplicated and validated; blank or "*" entries are invalid. Optional users filters order owners case-insensitively and combines with coins using AND semantics.
The first frame has snapshot: true, sequence: 1, and NEW diffs for every matching resting order. Later frames are block-ordered. A fully filtered frame is still sent with empty diffs so the sequence stays contiguous. This stream does not synthesize HIP-4 mirror orders.
package main
import (
"context"
"crypto/tls"
"errors"
"io"
"log"
"os"
"os/signal"
"syscall"
pb "example.com/hyperliquid-v3-client/gen/v3"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
)
func main() {
endpoint := os.Getenv("HYPERLIQUID_GRPC_ENDPOINT")
apiKey := os.Getenv("DWELLIR_API_KEY")
if endpoint == "" || apiKey == "" {
log.Fatal("set HYPERLIQUID_GRPC_ENDPOINT and DWELLIR_API_KEY")
}
conn, err := grpc.NewClient(endpoint, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{MinVersion: tls.VersionTLS12})))
if err != nil {
log.Fatal(err)
}
defer conn.Close()
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
ctx = metadata.AppendToOutgoingContext(ctx, "x-api-key", apiKey)
stream, err := pb.NewMarketStreamingClient(conn).StreamL4OrderUpdates(ctx, &pb.L4OrderUpdatesRequest{
Coins: []string{"BTC", "ETH"},
Users: []string{"0x1111111111111111111111111111111111111111"},
})
if err != nil {
log.Fatal(err)
}
var last uint64
for {
update, err := stream.Recv()
if errors.Is(err, io.EOF) {
return
}
if err != nil {
log.Fatal(err)
}
if update.GetSequence() != last+1 {
log.Fatalf("sequence gap: got=%d expected=%d", update.GetSequence(), last+1)
}
last = update.GetSequence()
log.Printf("block=%d snapshot=%t sequence=%d diffs=%d", update.GetBlockNumber(), update.GetSnapshot(), update.GetSequence(), len(update.GetDiffs()))
}
}Sequencing and recovery
Require each sequence to follow the last accepted value. A gap, ABORTED, or a stream state reset requires a reconnect and a full rebuild from the new snapshot. Treat an UPDATE or REMOVE for an unknown oid as a no-op. See the shared market-stream contract for common errors.
Related references: StreamL4Book and StreamTpslUpdates.
StreamL4Book - Stream Full L4 Order Book
Subscribe to a typed Hyperliquid L4 opening snapshot followed by native per-block order-book diffs over V3 gRPC.
StreamTpslUpdates - Stream TP/SL Order Updates
Reconstruct Hyperliquid take-profit and stop-loss trigger orders from typed snapshots and sequenced V3 gRPC diffs.