Docs

GetFills - Get Fill Data

Retrieve fills at a specific position from Hyperliquid L1 Gateway via gRPC. Get order execution data for analysis and reconciliation.

Retrieve fills at a specific position from the Hyperliquid L1 Gateway.

Full Code Examples

Clone our gRPC Code Examples Repository for complete, runnable implementations in Go, Python, and Node.js.

When to Use This Method

GetFills is essential for:

  • Trade Reconciliation - Verify fills at a specific point in time
  • Historical Analysis - Retrieve fill data for backtesting or reporting
  • Auditing - Verify trade executions at specific blocks
  • Liquidation Detection - Identify forced position closures at specific blocks
  • Debugging - Investigate specific fills during development

Method Signature

protobuf
rpc GetFills(Position) returns (BlockFills) {}

Common Use Cases

1. PnL Reconciliation

Python
def reconcile_pnl(client, metadata, start_block, end_block):
    """Calculate total PnL between two blocks"""
    pnl_by_address = {}

    for block_height in range(start_block, end_block + 1):
        request = hyperliquid_pb2.Position(block_height=block_height)
        response = client.GetFills(request, metadata=metadata)
        fills = json.loads(response.data)

        for event in fills.get('events', []):
            if len(event) >= 2:
                address = event[0]
                fill = event[1]
                pnl = float(fill.get('closedPnl', 0))

                if address not in pnl_by_address:
                    pnl_by_address[address] = 0
                pnl_by_address[address] += pnl

    return pnl_by_address

2. Fill Verification

Go
func verifyFill(client pb.HyperliquidL1GatewayClient, ctx context.Context, blockHeight int64, traderId string) []map[string]interface{} {
    request := &pb.Position{Position: &pb.Position_BlockHeight{BlockHeight: blockHeight}}
    response, _ := client.GetFills(ctx, request)

    var fills map[string]interface{}
    json.Unmarshal(response.Data, &fills)

    var traderFills []map[string]interface{}
    events := fills["events"].([]interface{})

    for _, event := range events {
        eventArr := event.([]interface{})
        if len(eventArr) >= 2 {
            address := eventArr[0].(string)
            if address == traderId {
                fillData := eventArr[1].(map[string]interface{})
                traderFills = append(traderFills, fillData)
            }
        }
    }

    return traderFills
}

3. Volume Analysis

JavaScript
function analyzeVolume(fills) {
    const volumeByCoin = {};
    const events = fills.events || [];

    for (const event of events) {
        if (event.length >= 2) {
            const fill = event[1];
            const coin = fill.coin;
            const volume = parseFloat(fill.sz) * parseFloat(fill.px);

            if (!volumeByCoin[coin]) {
                volumeByCoin[coin] = {
                    totalVolume: 0,
                    buyVolume: 0,
                    sellVolume: 0,
                    fillCount: 0
                };
            }

            volumeByCoin[coin].totalVolume += volume;
            volumeByCoin[coin].fillCount++;

            if (fill.side === 'B') {
                volumeByCoin[coin].buyVolume += volume;
            } else {
                volumeByCoin[coin].sellVolume += volume;
            }
        }
    }

    return volumeByCoin;
}

4. Liquidation Detection

Python
def find_liquidations(client, metadata, block_height):
    """Find liquidation events at a specific block"""
    request = hyperliquid_pb2.Position(block_height=block_height)
    response = client.GetFills(request, metadata=metadata)
    fills = json.loads(response.data)

    liquidations = []
    for event in fills.get('events', []):
        if len(event) >= 2:
            address = event[0]
            fill = event[1]

            liq = fill.get('liquidation')
            if liq and liq['liquidatedUser'] == address and 'Close' in fill.get('dir', ''):
                liquidations.append({
                    'user': address,
                    'coin': fill['coin'],
                    'size': fill['sz'],
                    'price': fill['px'],
                    'mark_price': liq['markPx'],
                    'method': liq['method'],
                    'pnl': fill['closedPnl']
                })

    return liquidations

Fill Field Reference

GetFills returns the same fill format as StreamFills. See the StreamFills documentation for the complete field reference, including liquidation data and maker vs taker details.

Best Practices

  1. Position Selection: Use block height for precise queries; timestamps may return different fills across requests
  2. Data Validation: Always validate JSON structure and handle optional fields
  3. Deduplication: Use tid (trade ID) as the unique identifier for deduplication
  4. Error Recovery: Implement retry logic with exponential backoff
  5. Resource Management: Close gRPC connections properly to avoid resource leaks

Current Limitations

  • Data Retention: Historical fill data is limited to a 24-hour rolling window
  • Rate Limits: Be mindful of request frequency to avoid overwhelming the service

Resources

Need help? Contact our support team or check the Hyperliquid gRPC documentation.