# StreamL4Book - Stream Full L4 Order Book

`StreamL4Book` exposes the full per-order book for one coin. The first frame is a typed snapshot; later frames carry the node-native JSON diff object in `data`.

## Request and opening behavior

`coin` is required and validated case-sensitively. Omitted `mirror` defaults to `true`, enabling HIP-4 binary-sibling projection. Mirrored orders set `synthetic: true` and have bit 52 set in `oid`.

The snapshot contains typed `L4Order` rows. Each later `diff` contains JSON-encoded `{order_statuses, book_diffs}` plus its block time and sequential block number.

The opening snapshot can exceed the client inbound message limit. The Go example sets a 64 MiB receive allowance as a practical starting point; tune it for the selected coin and workload while keeping memory use bounded.

## Request Parameters

- `coin` (`string, required`): One case-sensitive native coin identifier, validated against the enabled market universe.
- `mirror` (`optional bool, optional`): Enables HIP-4 sibling projection; omission defaults to true.

## Request Example

```go
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"
    "google.golang.org/protobuf/proto"
)

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})),
        grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(64 * 1024 * 1024)),
    )
    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).StreamL4Book(ctx, &pb.L4BookRequest{Coin: "BTC", Mirror: proto.Bool(true)})
    if err != nil {
        log.Fatal(err)
    }
    for {
        update, err := stream.Recv()
        if errors.Is(err, io.EOF) {
            return
        }
        if err != nil {
            log.Fatal(err)
        }
        if snapshot := update.GetSnapshot(); snapshot != nil {
            log.Printf("snapshot coin=%s block=%d bids=%d asks=%d", snapshot.GetCoin(), snapshot.GetBlockNumber(), len(snapshot.GetBids()), len(snapshot.GetAsks()))
            continue
        }
        diff := update.GetDiff()
        log.Printf("diff block=%d json_bytes=%d", diff.GetBlockNumber(), len(diff.GetData()))
    }
}
```

## Response Fields

- `snapshot` (`L4BookSnapshot, optional`): Opening branch of the update oneof; contains the complete typed L4 book.
- `snapshot.coin` (`string, required`): Native coin identifier.
- `snapshot.time` (`int64, required`): Snapshot block time in Unix milliseconds.
- `snapshot.block_number` (`int64, required`): Sequential Hyperliquid block number.
- `snapshot.bids` (`repeated L4Order, required`): Resting bid orders, highest price first.
- `snapshot.bids.user` (`string, required`): Owner address.
- `snapshot.bids.coin` (`string, required`): Native coin identifier.
- `snapshot.bids.side` (`string, required`): Native side B or A.
- `snapshot.bids.limit_px` (`string, required`): Limit price as a decimal string.
- `snapshot.bids.sz` (`string, required`): Resting size as a decimal string.
- `snapshot.bids.oid` (`uint64, required`): Order identifier; synthetic mirror orders have bit 52 set.
- `snapshot.bids.timestamp` (`int64, required`): Order placement time in Unix milliseconds.
- `snapshot.bids.trigger_condition` (`string, required`): Native trigger condition.
- `snapshot.bids.is_trigger` (`bool, required`): Whether this is a trigger order.
- `snapshot.bids.trigger_px` (`string, required`): Trigger price as a decimal string.
- `snapshot.bids.is_position_tpsl` (`bool, required`): Whether this is position-level TP/SL.
- `snapshot.bids.reduce_only` (`bool, required`): Whether the order is reduce-only.
- `snapshot.bids.order_type` (`string, required`): Native order type.
- `snapshot.bids.tif` (`optional string, optional`): Time-in-force value when present.
- `snapshot.bids.cloid` (`optional string, optional`): Client order identifier when present.
- `snapshot.bids.synthetic` (`bool, required`): True only for a synthesized HIP-4 mirror order.
- `snapshot.asks` (`repeated L4Order, required`): Resting ask orders, lowest price first.
- `snapshot.asks.user` (`string, required`): Owner address.
- `snapshot.asks.coin` (`string, required`): Native coin identifier.
- `snapshot.asks.side` (`string, required`): Native side B or A.
- `snapshot.asks.limit_px` (`string, required`): Limit price as a decimal string.
- `snapshot.asks.sz` (`string, required`): Resting size as a decimal string.
- `snapshot.asks.oid` (`uint64, required`): Order identifier; synthetic mirror orders have bit 52 set.
- `snapshot.asks.timestamp` (`int64, required`): Order placement time in Unix milliseconds.
- `snapshot.asks.trigger_condition` (`string, required`): Native trigger condition.
- `snapshot.asks.is_trigger` (`bool, required`): Whether this is a trigger order.
- `snapshot.asks.trigger_px` (`string, required`): Trigger price as a decimal string.
- `snapshot.asks.is_position_tpsl` (`bool, required`): Whether this is position-level TP/SL.
- `snapshot.asks.reduce_only` (`bool, required`): Whether the order is reduce-only.
- `snapshot.asks.order_type` (`string, required`): Native order type.
- `snapshot.asks.tif` (`optional string, optional`): Time-in-force value when present.
- `snapshot.asks.cloid` (`optional string, optional`): Client order identifier when present.
- `snapshot.asks.synthetic` (`bool, required`): True only for a synthesized HIP-4 mirror order.
- `diff` (`L4BookDiff, optional`): Post-snapshot branch of the update oneof; carries one node-native per-block diff.
- `diff.time` (`int64, required`): Diff block time in Unix milliseconds.
- `diff.block_number` (`int64, required`): Sequential Hyperliquid block number.
- `diff.data` (`bytes, required`): JSON-encoded object containing order_statuses and book_diffs.

## Successful Response

```protobuf
snapshot: {
  coin: "BTC"
  time: 1785736814057
  block_number: 1058646974
  bids: {
    user: "0x1111111111111111111111111111111111111111"
    coin: "BTC"
    side: "B"
    limit_px: "114250.0"
    sz: "0.25"
    oid: 123456789
    timestamp: 1785736813000
    trigger_condition: "N/A"
    is_trigger: false
    trigger_px: "0.0"
    is_position_tpsl: false
    reduce_only: false
    order_type: "Limit"
    tif: "Gtc"
    cloid: "0x00112233445566778899aabbccddeeff"
    synthetic: false
  }
}
```

## Error Responses

### Invalid request

- Code: `INVALID_ARGUMENT`
- Description: The required coin is empty, unknown, unavailable, or malformed.

### Feature unavailable

- Code: `FAILED_PRECONDITION`
- Description: This stream is unavailable on the selected endpoint.

### View unavailable

- Code: `UNAVAILABLE`
- Description: The requested order-book view is not ready.

### Lost incremental state

- Code: `ABORTED`
- Description: Frame loss, a stream state reset, or a HIP-4 market-shape change requires rebuilding from a new snapshot.

### Slow consumer

- Code: `DEADLINE_EXCEEDED`
- Description: The consumer was too slow; reconnect.

### Unauthenticated

- Code: `UNAUTHENTICATED`
- Description: Usable x-api-key metadata was not supplied.

### Permission denied

- Code: `PERMISSION_DENIED`
- Description: The supplied credential cannot call this service.

## Delivery and recovery

This is an incremental stream. Frame loss, a stream state reset, or an outcome market changing shape closes it with `ABORTED`. Reconnect and rebuild from the next opening snapshot. For typed order-level diffs without native JSON, use `StreamL4OrderUpdates`. Shared live-stream and error semantics are on the [gRPC overview](https://www.dwellir.com/docs/hyperliquid/grpc#v3-market-streaming-service).

Related references: [StreamL4OrderUpdates](https://www.dwellir.com/docs/hyperliquid/stream_l4_order_updates) and the [Order Book WebSocket L4 book](https://www.dwellir.com/docs/hyperliquid/l4-book).
