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

# Watch Blocks \[block.watch]

Watches incoming blocks, returning a watcher handle.

The watcher subscribes to `newHeads` with `eth_subscribe` when the Client uses a WebSocket or IPC transport. Otherwise, the watcher polls `eth_getBlockByNumber`.

The source starts when the first listener or iterator attaches.

## Usage

This example watches incoming blocks, returning a watcher handle.

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

const watch = client.block.watch()

watch.onBlock((block) => console.log(block.number))
// @log: 19868020n

// later: stop watching
watch.off()
```

```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.block.watch` directly by passing the Client as the first argument.

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

const watch = Actions.block.watch(client)

watch.onBlock((block) => console.log(block.number))
// @log: 19868020n

// later: stop watching
watch.off()
```

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

### Emit the Current Full Block

Set `emitOnBegin` to emit immediately and `includeTransactions` to include full transaction objects.

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

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

const watch = client.block.watch({
  emitOnBegin: true, // [!code focus]
  includeTransactions: true, // [!code focus]
})

watch.onBlock((block) => console.log(block.transactions))
```

### Backfill Missed Blocks

Enable polling and `emitMissed` to fetch blocks that arrive between polling intervals.

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

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

const watch = client.block.watch({
  emitMissed: true, // [!code focus]
  poll: true, // [!code focus]
  pollingInterval: 2_000, // [!code focus]
})

watch.onBlock((block) => console.log(block.number))
```

## Return Value

`Watcher`

A watcher handle with the following members:

#### onBlock

* **Type:** `(fn: (block: Block, prevBlock: Block | undefined) => void) => () => void`

Registers a listener invoked with each new block. Starts the watcher on first registration. Returns a function that unregisters the listener.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const watch = Actions.block.watch(client)

const off = watch.onBlock((block, prevBlock) => { // [!code focus]
  console.log(block, prevBlock) // [!code focus]
}) // [!code focus]

// later: unregister just this listener
off()
```

#### onError

* **Type:** `(fn: (error: Error) => void) => () => void`

Registers a listener invoked when fetching a new block fails. Returns a function that unregisters the listener.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const watch = Actions.block.watch(client)
watch.onBlock(() => {})

watch.onError((error) => console.error(error)) // [!code focus]
```

#### off

* **Type:** `() => void`

Tears down the watcher: removes all listeners, ends all iterators, and stops the underlying polling or subscription. Idempotent and terminal.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const watch = Actions.block.watch(client)
watch.onBlock((block) => console.log(block.number))

watch.off() // [!code focus]
```

#### `[Symbol.asyncIterator]`

* **Type:** `() => AsyncIterableIterator<{ block: Block; prevBlock: Block | undefined }>`

Async-iterates emitted blocks. The iterator is a latest-only state stream (it may skip intermediate values under slow consumption) and throws if the source errors.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const watch = Actions.block.watch(client)

for await (const { block } of watch) // [!code focus]
  console.log(block.number) // [!code focus]
```

## Parameters

### blockTag

* **Type:** `'latest' | 'earliest' | 'pending' | 'safe' | 'finalized'`
* **Default:** `'latest'`

The block tag to watch.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const watch = Actions.block.watch(client, {
  blockTag: 'safe', // [!code focus]
})
watch.onBlock((block) => console.log(block.number))
```

### emitMissed

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

Whether to emit the blocks missed between polls (for example, when the block number jumps by more than one between intervals).

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const watch = Actions.block.watch(client, {
  emitMissed: true, // [!code focus]
})
watch.onBlock((block) => console.log(block.number))
```

### emitOnBegin

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

Whether to emit the latest block when the watcher opens.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const watch = Actions.block.watch(client, {
  emitOnBegin: true, // [!code focus]
})
watch.onBlock((block) => console.log(block.number))
```

### includeTransactions

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

Whether to include full transaction objects in each emitted block.

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const watch = Actions.block.watch(client, {
  includeTransactions: true, // [!code focus]
})
watch.onBlock((block) => console.log(block.transactions))
```

### poll

* **Type:** `boolean`
* **Default:** `false` for WebSocket or IPC transports, `true` otherwise

Whether to poll for new blocks instead of using a subscription. Defaults to `true` when the transport cannot subscribe.

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

const client = Client.create({ chain: mainnet, transport: webSocket() })
// ---cut---
const watch = Actions.block.watch(client, {
  poll: true, // [!code focus]
})
watch.onBlock((block) => console.log(block.number))
```

### pollingInterval

* **Type:** `number`
* **Default:** `client.pollingInterval`

Polling frequency (in milliseconds).

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

const client = Client.create({ chain: mainnet, transport: http() })
// ---cut---
const watch = Actions.block.watch(client, {
  pollingInterval: 1_000, // [!code focus]
})
watch.onBlock((block) => console.log(block.number))
```
