# StreamCandle - Stream Live OHLCV Candles

`StreamCandle` sends live snapshots of one epoch-aligned OHLCV bucket for a `(coin, interval)` pair. It is a live view, not the historical candle product.

## Request and opening behavior

Both `coin` and `interval` are required. Supported intervals are `1s`, `1m`, `3m`, `5m`, `15m`, `30m`, `1h`, `2h`, `4h`, `8h`, `12h`, and `1d`.

If the gateway already tracks the bucket, its current state arrives immediately. A cold subscription waits for the next execution, so its first bucket can be partial. Buckets are sparse: no execution means no frame. A new `open_time` signals rollover, and the previous bucket's final frame is sent first.

## Request Parameters

- `coin` (`string, required`): One case-sensitive native coin identifier, validated against the enabled market universe.
- `interval` (`string, required`): One of the 12 fixed-width intervals: 1s, 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 8h, 12h, or 1d.

## Request Example

```go
package main

import (
    "context"
    "crypto/tls"
    "log"
    "os"

    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, apiKey := os.Getenv("HYPERLIQUID_GRPC_ENDPOINT"), 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 := metadata.AppendToOutgoingContext(context.Background(), "x-api-key", apiKey)
    stream, err := pb.NewMarketStreamingClient(conn).StreamCandle(ctx, &pb.CandleRequest{Coin: "BTC", Interval: "1m"})
    if err != nil {
        log.Fatal(err)
    }
    for {
        update, err := stream.Recv()
        if err != nil {
            log.Fatal(err)
        }
        log.Printf("coin=%s interval=%s open_time=%d OHLC=%s/%s/%s/%s volume=%s trades=%d", update.GetCoin(), update.GetInterval(), update.GetOpenTime(), update.GetOpen(), update.GetHigh(), update.GetLow(), update.GetClose(), update.GetVolume(), update.GetTradeCount())
    }
}
```

## Response Fields

- `coin` (`string, required`): Native coin identifier.
- `interval` (`string, required`): Requested fixed-width interval.
- `open_time` (`int64, required`): Epoch-aligned bucket-open time in Unix milliseconds.
- `close_time` (`int64, required`): Bucket open time plus interval width minus 1 millisecond.
- `open` (`string, required`): First execution price in source order.
- `high` (`string, required`): Highest execution price in the bucket.
- `low` (`string, required`): Lowest execution price in the bucket.
- `close` (`string, required`): Last execution price in source order.
- `volume` (`string, required`): Exact decimal sum of base-unit execution volume.
- `trade_count` (`uint64, required`): Number of executions; one matched pair counts once.

## Successful Response

```protobuf
coin: "BTC"
interval: "1m"
open_time: 1785736800000
close_time: 1785736859999
open: "114200.0"
high: "114275.0"
low: "114190.0"
close: "114250.0"
volume: "18.75"
trade_count: 143
```

## Error Responses

### Invalid request

- Code: `INVALID_ARGUMENT`
- Description: The coin is malformed or unavailable, or interval is not one of the 12 supported values.

### Feature unavailable

- Code: `FAILED_PRECONDITION`
- Description: Candle streaming is unavailable on the selected endpoint.

### View unavailable

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

### Stream state reset

- Code: `ABORTED`
- Description: The stream state reset; reconnect to resume live bucket updates.

### 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

Frames with the same `open_time` supersede earlier frames. Subscriber lag is recoverable for an open bucket, although a dropped closing frame can only be inferred from a later `open_time`. `FAILED_PRECONDITION` means candle streaming is unavailable; `ABORTED` means the stream state reset. See the [gRPC overview](https://www.dwellir.com/docs/hyperliquid/grpc#v3-market-streaming-service) for shared errors.

Related reference: [Hyperliquid Index candles](https://www.dwellir.com/docs/hyperliquid/hyperliquid-index/ohlcv-data/candles).
