> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://v3.viem.sh/api/mcp` to find what you need.

# Create Event Filter \[event.createFilter]

Creates a filter to listen for new event logs.

Poll the filter with [`Actions.filter.getChanges`](/docs/actions/public/filter/getChanges). Use [`Actions.filter.getLogs`](/docs/actions/public/filter/getLogs) to read the full set.

Call [`Actions.filter.uninstall`](/docs/actions/public/filter/uninstall) when you finish. Viem decodes matching logs with the events stored by the filter.

## Usage

This example creates a filter to listen for new event logs.

:::code-group
```ts twoslash [example.ts]
import { AbiEvent } from 'viem/utils'
import { client } from './viem.config'

const filter = await client.event.createFilter({
  event: AbiEvent.from(
    'event Transfer(address indexed from, address indexed to, uint256 value)',
  ),
})
// @log: { abiEvent: [...], id: '0x...', request: ƒ, strict: false, type: 'event' }
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, http, publicActions } from 'viem'
import { mainnet } from 'viem/chains'

export const client = Client.create({
  chain: mainnet,
  transport: http(),
}).extend(publicActions())
```
:::

### Standalone Action

Call `Actions.event.createFilter` directly by passing the Client as the first argument.

:::code-group
```ts twoslash [example.ts]
import { Actions } from 'viem'
import { AbiEvent } from 'viem/utils'
import { client } from './viem.config'

const filter = await Actions.event.createFilter(client, {
  event: AbiEvent.from(
    'event Transfer(address indexed from, address indexed to, uint256 value)',
  ),
})
// @log: { abiEvent: [...], id: '0x...', request: ƒ, strict: false, type: 'event' }
```

```ts twoslash [viem.config.ts] filename="viem.config.ts"
import { Client, http } from 'viem'
import { mainnet } from 'viem/chains'

export const client = Client.create({
  chain: mainnet,
  transport: http(),
})
```
:::

## Recipes

Use a Client method or pass the Client to the standalone action.

### Filtering by Multiple Events

Pass `events` to listen for and decode several events with one filter.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'
import { AbiEvent } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
const filter = await Actions.event.createFilter(client, {
  events: [ // [!code focus]
    AbiEvent.from('event Transfer(address indexed from, address indexed to, uint256 value)'), // [!code focus]
    AbiEvent.from('event Approval(address indexed owner, address indexed spender, uint256 value)'), // [!code focus]
  ], // [!code focus]
})

const logs = await Actions.filter.getChanges(client, { filter })
//    ^?
```

### Filtering by Indexed Arguments

Pass `args` to filter logs by the event's indexed arguments.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'
import { AbiEvent } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
const filter = await Actions.event.createFilter(client, {
  event: AbiEvent.from(
    'event Transfer(address indexed from, address indexed to, uint256 value)',
  ),
  args: { // [!code focus]
    from: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045', // [!code focus]
  }, // [!code focus]
})
```

## Return Value

`Actions.filter.Filter<'event'>`

An event filter. Its `request` function uses the transport that created the filter ID.

The filter stores `abiEvent`, `args`, and `strict` for [`Actions.filter.getChanges`](/docs/actions/public/filter/getChanges) and [`Actions.filter.getLogs`](/docs/actions/public/filter/getLogs).

## Parameters

### address

* **Type:** `Address | Address[]`

Address or list of addresses from which logs originated.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const filter = await Actions.event.createFilter(client, {
  address: '0xfba3912ca04dd458c843e2ee08967fc04f3579c2', // [!code focus]
})
```

### args

* **Type:** Inferred from `event`.

Indexed argument values to filter logs by.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'
import { AbiEvent } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const filter = await Actions.event.createFilter(client, {
  event: AbiEvent.from(
    'event Transfer(address indexed from, address indexed to, uint256 value)',
  ),
  args: { from: '0xd8da6bf26964af9d7eed9e03e53415d37aa96045' }, // [!code focus]
})
```

### event

* **Type:** `AbiEvent`

Event to filter and decode logs by. Mutually exclusive with `events`.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'
import { AbiEvent } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const filter = await Actions.event.createFilter(client, {
  event: AbiEvent.from( // [!code focus]
    'event Transfer(address indexed from, address indexed to, uint256 value)', // [!code focus]
  ), // [!code focus]
})
```

### events

* **Type:** `readonly AbiEvent[]`

Events to filter and decode logs by. Mutually exclusive with `event`.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'
import { AbiEvent } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const filter = await Actions.event.createFilter(client, {
  events: [ // [!code focus]
    AbiEvent.from('event Transfer(address indexed from, address indexed to, uint256 value)'), // [!code focus]
  ], // [!code focus]
})
```

### fromBlock

* **Type:** `bigint | BlockTag`

Block number or tag after which to include logs.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'
import { AbiEvent } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const filter = await Actions.event.createFilter(client, {
  event: AbiEvent.from(
    'event Transfer(address indexed from, address indexed to, uint256 value)',
  ),
  fromBlock: 19_760_000n, // [!code focus]
})
```

### strict

* **Type:** `boolean`
* **Default:** `false`

Whether the logs must match the indexed/non-indexed arguments on `event`. When `true`, only logs whose arguments fully decode are returned.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'
import { AbiEvent } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const filter = await Actions.event.createFilter(client, {
  event: AbiEvent.from(
    'event Transfer(address indexed from, address indexed to, uint256 value)',
  ),
  strict: true, // [!code focus]
})
```

### toBlock

* **Type:** `bigint | BlockTag`

Block number or tag before which to include logs.

```ts twoslash
import { Actions, Client, http } from 'viem'
import { mainnet } from 'viem/chains'
import { AbiEvent } from 'viem/utils'

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const filter = await Actions.event.createFilter(client, {
  event: AbiEvent.from(
    'event Transfer(address indexed from, address indexed to, uint256 value)',
  ),
  toBlock: 19_760_100n, // [!code focus]
})
```

## Errors

| Error | Description |
| --- | --- |
| `AbiEvent.FilterTypeNotSupportedError` | `args` includes an indexed tuple or array, which event topic filters do not support. |
| `AbiParameters.InvalidTypeError` | `args` includes an indexed ABI type that the topic encoder does not support. |
| `Address.InvalidAddressError` | `args` includes an invalid indexed address. |
| `Hex.IntegerOutOfRangeError` | `args` includes an indexed integer outside the supported 256-bit range. |
| `Hex.SizeExceedsPaddingSizeError` | An indexed fixed-bytes value exceeds the 32-byte topic size. |
