> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bloklake.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Filters

> Select logs by contract and topics, and transactions by sender, recipient, function, status and type.

`logs` and `transactions` are each a list of **filter objects**.

* Within one object, every field you set must match (**AND**).
* A row is returned if it matches **any** object in the list (**OR**).
* Within one field, the row's value must be **one of** the listed values (**IN**).
* An object with no fields set (`{}`) matches every row of that type in the range.

## Log filters

| Key | Type | Matches |
| - | - | - |
| `address` | array of 20-byte hex | the contract that emitted the log |
| `topic0` | array of 32-byte hex | the event signature hash |
| `topic1`, `topic2`, `topic3` | array of 32-byte hex | the indexed event arguments |
| `addressSet` | set id | like `address`, from a [set](https://docs.bloklake.com/querying/sets.md) |
| `topic0Set` … `topic3Set` | set id | like `topicN`, from a set |

### Examples

Every `Transfer` and `Approval` of two tokens:

```json theme={null}
{
  "logs": [{
    "address": ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "0xdac17f958d2ee523a2206206994597c13d831ec7"],
    "topic0": [
      "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
      "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"
    ]
  }]
}
```

Every `Transfer` of any token **to** one wallet (the recipient is `topic2`):

```json theme={null}
{
  "logs": [{
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
    "topic2": ["0x000000000000000000000000d8da6bf26964af9d7eed9e49c3e2f8d4c3c7c1c9"]
  }]
}
```

Transfers **from or to** a wallet: two objects, because a row matches if either one does:

```json theme={null}
{
  "logs": [
    {"topic0": ["0xddf252ad…b3ef"], "topic1": ["0x000000000000000000000000d8da6bf2…"]},
    {"topic0": ["0xddf252ad…b3ef"], "topic2": ["0x000000000000000000000000d8da6bf2…"]}
  ]
}
```

> [!WARNING]
>
> **Topics are 32 bytes.** An address in a topic is left-padded with 12 zero bytes:
> `0x000000000000000000000000` + the 40 hex characters of the address. Passing a 20-byte address
> as a topic is a `400`.

> [!TIP]
>
> Event signature hashes are `keccak256` of the event signature, e.g.
> `keccak256("Transfer(address,address,uint256)")`. With viem: `toEventSelector("Transfer(address,address,uint256)")`;
> with ethers: `ethers.id("Transfer(address,address,uint256)")`; with web3.py:
> `Web3.keccak(text="Transfer(address,address,uint256)").hex()`.

## Transaction filters

| Key | Type | Matches |
| - | - | - |
| `from` | array of 20-byte hex | the sender |
| `to` | array of 20-byte hex | the recipient (contract creations have no `to` and never match) |
| `sighash` | array of 4-byte hex | the function selector: the first 4 bytes of `input` |
| `status` | `0` or `1` | the receipt status: `1` succeeded, `0` reverted |
| `type` | array of integers 0–255 | the transaction type: `0` legacy, `1` access list, `2` EIP-1559, `3` blob, `4` EIP-7702, and chain-specific types (Arbitrum's `100`–`106` and `120`) |
| `fromSet`, `toSet` | set id | like `from` / `to`, from a [set](https://docs.bloklake.com/querying/sets.md) |

### Examples

Every `transfer(address,uint256)` call (selector `0xa9059cbb`) to USDC:

```json theme={null}
{
  "transactions": [{
    "to": ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"],
    "sighash": ["0xa9059cbb"]
  }]
}
```

Everything a wallet sent or received:

```json theme={null}
{
  "transactions": [
    {"from": ["0xd8da6bf26964af9d7eed9e49c3e2f8d4c3c7c1c9"]},
    {"to": ["0xd8da6bf26964af9d7eed9e49c3e2f8d4c3c7c1c9"]}
  ]
}
```

Only the reverted calls to a contract:

```json theme={null}
{"transactions": [{"to": ["0x7a250d5630b4cf539739df2c5dacb4c659f2488d"], "status": 0}]}
```

Every blob transaction, and every legacy transaction to a contract:

```json theme={null}
{
  "transactions": [
    {"type": [3]},
    {"to": ["0x7a250d5630b4cf539739df2c5dacb4c659f2488d"], "type": [0]}
  ]
}
```

### How `status` works

`status` is applied to the matches, not used to find them: the server finds the transactions
matching the other keys, then drops the ones with the wrong status before counting or sending
anything. Two consequences:

* Every transaction object in a request must carry the same `status`, or none:
  `[{"status": 1}, {"sighash": [...]}]` is a `400`.
* A filter with **only** `status` reads the status of every transaction in the range. Give it a
  range or other keys.

Transactions from before Byzantium (Ethereum block 4,370,000) have no receipt status and never
match a `status` filter.

### How `type` works

`type` is also checked on the matches rather than looked up in an index, but it works like any
other key of its object: it is ANDed with that object's other keys, and different objects can
ask for different types, or none, as in the example above. It doesn't apply to the
transactions [`joinTransactions`](https://docs.bloklake.com/querying/join-transactions) adds.

A filter with **only** `type` reads the type of every transaction in the range. That costs one
byte per transaction, so it is fast (about 50 ms for 50,000 Robinhood Chain blocks), but other
keys narrow it further.

## Value rules

* Hex values are `0x`-prefixed, case-insensitive, and must be exactly the field's width:
  40 hex characters for addresses, 64 for topics, 8 for sighashes. A wrong length is a `400`
  naming the offending value (`logs[0].address[0]: …`).
* Duplicates are fine; the server removes them. Order doesn't matter.
* An `address` list and an `addressSet` in the same object are combined (union), not
  exclusive. The same goes for every `X` / `XSet` pair.
* Up to 256 filter objects per row type and 100,000 values per field. For larger lists, use a
  [set](https://docs.bloklake.com/querying/sets.md).

## What you can't filter on

Only the fields above can be filtered on. Everything else (`value`, `gasUsed`, `input` beyond the
first four bytes, block `miner`, log `data`, …) can be [returned](https://docs.bloklake.com/querying/fields.md) but not
filtered on. Filter as narrowly as these fields allow, then filter the rest client-side.

Blocks can't be filtered at all, beyond the range. You get every block in the range (no
`logs`/`transactions` filter) or exactly the blocks that contain a match (with one). See
[Blocks](https://docs.bloklake.com/querying/blocks.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.