# StreamLiquidationFills - Stream Liquidation Fills

`StreamLiquidationFills` sends fills that carry liquidation metadata. `liquidated_users` targets `fill.liquidation.liquidated_user`, not the account in `fill.user`.

## Request and live-only behavior

Empty `coins` and `liquidated_users` lists select all liquidation fills. Coins match exactly. Liquidated-user addresses match case-insensitively, and the two filters combine using AND semantics. Unknown coin values simply never match.

The stream has no opening snapshot or backfill. Frames emptied by filtering remain present so the per-subscription `sequence` stays contiguous.

## Request Parameters

- `coins` (`repeated string, optional`): Optional exact coin scope; empty means all coins, and unknown coins simply never match.
- `liquidated_users` (`repeated string, optional`): Optional addresses matched case-insensitively against liquidation.liquidated_user.

## 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).StreamLiquidationFills(ctx, &pb.LiquidationFillsRequest{
        Coins: []string{"BTC", "ETH"},
        LiquidatedUsers: []string{"0x3333333333333333333333333333333333333333"},
    })
    if err != nil {
        log.Fatal(err)
    }
    var last uint64
    for {
        update, err := stream.Recv()
        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 sequence=%d fills=%d", update.GetBlockNumber(), update.GetSequence(), len(update.GetFills()))
    }
}
```

## Response Fields

- `time` (`int64, required`): Source block time in Unix milliseconds.
- `block_number` (`int64, required`): Sequential Hyperliquid block number.
- `sequence` (`uint64, required`): Per-subscription monotonic counter beginning at 1 on the first live frame.
- `fills` (`repeated Fill, required`): Liquidation fills matching the requested liquidated accounts and coins; may be empty after filtering.
- `fills.user` (`string, required`): Account this fill belongs to.
- `fills.coin` (`string, required`): Native coin identifier.
- `fills.px` (`string, required`): Execution price as a decimal string.
- `fills.sz` (`string, required`): Executed size as a decimal string.
- `fills.side` (`string, required`): Native side B or A.
- `fills.time` (`int64, required`): Execution time in Unix milliseconds.
- `fills.hash` (`string, required`): Transaction hash.
- `fills.tid` (`uint64, required`): Within one block, use (coin, tid). Across blocks, include the frame's block_number. Retain account and order identity for individual fills.
- `fills.crossed` (`bool, required`): True when this account was the taker.
- `fills.dir` (`string, required`): Human-readable position direction.
- `fills.start_position` (`string, required`): Signed position immediately before this fill.
- `fills.oid` (`uint64, required`): Filled order identifier.
- `fills.closed_pnl` (`string, required`): Closed profit and loss as a decimal string.
- `fills.fee` (`string, required`): Trading fee as a decimal string.
- `fills.fee_token` (`string, required`): Fee denomination.
- `fills.builder` (`FillBuilder, optional`): Builder attribution, unset for fills without a builder.
- `fills.builder.address` (`string, required`): Builder address.
- `fills.builder.fee` (`string, required`): Builder fee charged on this fill.
- `fills.cloid` (`optional string, optional`): Client order identifier when present.
- `fills.twap_id` (`optional uint64, optional`): TWAP identifier when the fill came from a TWAP order.
- `fills.liquidation` (`FillLiquidation, optional`): Liquidation metadata; always present on a matched fill from this method.
- `fills.liquidation.liquidated_user` (`string, required`): Liquidated account address used by liquidated_users matching.
- `fills.liquidation.mark_px` (`string, required`): Liquidation mark price.
- `fills.liquidation.method` (`string, required`): Native liquidation method.

## Successful Response

```protobuf
time: 1785736814057
block_number: 1058646974
sequence: 1
fills: {
  user: "0x1111111111111111111111111111111111111111"
  coin: "BTC"
  px: "114250.0"
  sz: "0.25"
  side: "B"
  time: 1785736814057
  hash: "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
  tid: 99887766
  crossed: true
  dir: "Open Long"
  start_position: "0.0"
  oid: 123456789
  closed_pnl: "0.0"
  fee: "0.285625"
  fee_token: "USDC"
  builder: { address: "0x2222222222222222222222222222222222222222" fee: "0.01" }
  cloid: "0x00112233445566778899aabbccddeeff"
  twap_id: 778899
  liquidation: { liquidated_user: "0x3333333333333333333333333333333333333333" mark_px: "114200.0" method: "market" }
}
```

## Error Responses

### Invalid filter

- Code: `INVALID_ARGUMENT`
- Description: A coin entry or liquidated-user address is malformed.

### Feature unavailable

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

### View unavailable

- Code: `UNAVAILABLE`
- Description: Live fills are not currently available.

### Lost live fills

- Code: `ABORTED`
- Description: Frame loss or a stream state reset ended this live-only stream.

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

## Sequencing and recovery

Require contiguous `sequence` values. A gap or `ABORTED` means loss; reconnect for live data and recover the missing blocks through [StreamFills](https://www.dwellir.com/docs/hyperliquid/stream_fills) or [historical data](https://www.dwellir.com/docs/hyperliquid/historical-data). See the [gRPC overview](https://www.dwellir.com/docs/hyperliquid/grpc#v3-market-streaming-service) for shared errors.

Related references: [StreamAllFills](https://www.dwellir.com/docs/hyperliquid/stream_all_fills) and [StreamTrades](https://www.dwellir.com/docs/hyperliquid/stream_trades).
