# eth_newBlockFilter - XDC Network RPC Method

Creates a filter on XDC Network that notifies when new blocks arrive. Once created, poll the filter with `eth_getFilterChanges` to receive an array of block hashes for each new block added to the chain since your last poll.

> **Why XDC Network?** Build on the enterprise-grade blockchain for trade finance with 2-second finality and ISO 20022 compliance with ISO 20022 messaging, ITFA membership, Contour Network acquisition, 801M+ transactions, and partnerships with Circle and Deutsche Telekom.

## When to Use This Method

`eth_newBlockFilter` is essential for trade finance developers, enterprise blockchain teams, and RWA tokenization builders:

- **Block Monitoring** - Detect new blocks on XDC Network as they are mined or finalized, without repeatedly calling `eth_blockNumber`
- **Chain Progression Tracking** - Build dashboards or alerting systems that track block production rate and timing
- **Reorg Detection** - Identify chain reorganizations by monitoring for blocks that are replaced or missing
- **Event-Driven Architectures** - Trigger downstream processing (indexing, notifications, settlement) whenever a new block appears

## Best Practices

- Use WebSocket subscriptions (`eth_subscribe`) for real-time block notifications in production environments
- Poll with `eth_getFilterChanges` at 1-5 second intervals to receive new block hashes
- Combine with `eth_getBlockByNumber` or `eth_getBlockByHash` to retrieve full block details

## Request Parameters

This method accepts no parameters.

## Request Example

```json
{
  "jsonrpc": "2.0",
  "method": "eth_newBlockFilter",
  "params": [],
  "id": 1
}
```

## Response Fields

- `result` (`QUANTITY, required`): A hex-encoded filter ID used to poll for new blocks via eth_getFilterChanges
- `result` (`Array<DATA>, required`): Array of 32-byte block hashes for each new block since the last poll

## Successful Response

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x1a2b3c"
}
```

## Error Responses

### Error Response

- Code: `-32603`

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32603,
    "message": "Internal error"
  }
}
```

## Code Examples

cURL
JavaScript
Python
Go

```bash
# Create the block filter
FILTER_ID=$(curl -s -X POST https://api-xdc-mainnet.n.dwellir.com/YOUR_API_KEY \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "eth_newBlockFilter",
    "params": [],
    "id": 1
  }' | jq -r '.result')

echo "Filter ID: $FILTER_ID"

# Poll for new blocks
curl -X POST https://api-xdc-mainnet.n.dwellir.com/YOUR_API_KEY \
  -H "Content-Type: application/json" \
  -d "{
    \"jsonrpc\": \"2.0\",
    \"method\": \"eth_getFilterChanges\",
    \"params\": [\"$FILTER_ID\"],
    \"id\": 2
  }"
```

```javascript
import { JsonRpcProvider } from 'ethers';

const provider = new JsonRpcProvider('https://api-xdc-mainnet.n.dwellir.com/YOUR_API_KEY');

// Create a block filter
const filterId = await provider.send('eth_newBlockFilter', []);
console.log('Block filter created:', filterId);

// Poll for new blocks
async function pollNewBlocks(interval = 2000) {
  while (true) {
    const blockHashes = await provider.send('eth_getFilterChanges', [filterId]);
    if (blockHashes.length > 0) {
      for (const hash of blockHashes) {
        const block = await provider.getBlock(hash);
        console.log(`New block #${block.number} (${hash})`);
      }
    }
    await new Promise(r => setTimeout(r, interval));
  }
}

pollNewBlocks();
```

```python
import requests
import time

RPC_URL = 'https://api-xdc-mainnet.n.dwellir.com/YOUR_API_KEY'

def rpc_call(method, params):
    response = requests.post(RPC_URL, json={
        'jsonrpc': '2.0',
        'method': method,
        'params': params,
        'id': 1
    })
    return response.json()

# Create block filter
filter_result = rpc_call('eth_newBlockFilter', [])
filter_id = filter_result['result']
print(f'Block filter created: {filter_id}')

# Poll for new blocks
while True:
    changes = rpc_call('eth_getFilterChanges', [filter_id])
    block_hashes = changes.get('result', [])
    if block_hashes:
        for block_hash in block_hashes:
            print(f'New block: {block_hash}')
    time.sleep(2)
```

```go
package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/ethereum/go-ethereum/ethclient"
)

func main() {
    client, err := ethclient.Dial("https://api-xdc-mainnet.n.dwellir.com/YOUR_API_KEY")
    if err != nil {
        log.Fatal(err)
    }

    // Subscribe to new block headers
    headers := make(chan *types.Header)
    sub, err := client.SubscribeNewHead(context.Background(), headers)
    if err != nil {
        // Fallback: polling approach
        lastBlock, _ := client.BlockNumber(context.Background())
        ticker := time.NewTicker(2 * time.Second)

        for range ticker.C {
            currentBlock, err := client.BlockNumber(context.Background())
            if err != nil {
                log.Println("Error:", err)
                continue
            }
            if currentBlock > lastBlock {
                for b := lastBlock + 1; b <= currentBlock; b++ {
                    block, _ := client.BlockByNumber(context.Background(), new(big.Int).SetUint64(b))
                    if block != nil {
                        fmt.Printf("New block #%d: %s\n", block.Number().Uint64(), block.Hash().Hex())
                    }
                }
                lastBlock = currentBlock
            }
        }
        return
    }

    for {
        select {
        case err := <-sub.Err():
            log.Fatal(err)
        case header := <-headers:
            fmt.Printf("New block #%d: %s\n", header.Number.Uint64(), header.Hash().Hex())
        }
    }
}
```

## Common Use Cases

### 1. Block Production Rate Monitor

Track block times and detect slowdowns on XDC Network:

```javascript
async function monitorBlockRate(provider) {
  const filterId = await provider.send('eth_newBlockFilter', []);
  let lastBlockTime = null;
  const blockTimes = [];

  setInterval(async () => {
    const blockHashes = await provider.send('eth_getFilterChanges', [filterId]);

    for (const hash of blockHashes) {
      const block = await provider.getBlock(hash);
      const blockTime = block.timestamp;

      if (lastBlockTime) {
        const interval = blockTime - lastBlockTime;
        blockTimes.push(interval);

        // Keep last 100 block times
        if (blockTimes.length > 100) blockTimes.shift();

        const avgBlockTime = blockTimes.reduce((a, b) => a + b, 0) / blockTimes.length;
        console.log(`Block #${block.number} | interval: ${interval}s | avg: ${avgBlockTime.toFixed(1)}s`);

        if (interval > avgBlockTime * 3) {
          console.warn(`Slow block detected - ${interval}s vs ${avgBlockTime.toFixed(1)}s average`);
        }
      }
      lastBlockTime = blockTime;
    }
  }, 2000);
}
```

### 2. Reorg-Aware Block Tracker

Detect chain reorganizations by tracking block hashes:

```javascript
async function trackBlocksWithReorgDetection(provider) {
  const filterId = await provider.send('eth_newBlockFilter', []);
  const blockHistory = new Map(); // blockNumber -> blockHash

  setInterval(async () => {
    const newBlockHashes = await provider.send('eth_getFilterChanges', [filterId]);

    for (const hash of newBlockHashes) {
      const block = await provider.getBlock(hash);
      const existingHash = blockHistory.get(block.number);

      if (existingHash && existingHash !== hash) {
        console.warn(`Reorg detected at block #${block.number}!`);
        console.warn(`  Old hash: ${existingHash}`);
        console.warn(`  New hash: ${hash}`);
        // Trigger reorg handling logic
      }

      blockHistory.set(block.number, hash);

      // Prune old entries
      if (blockHistory.size > 1000) {
        const minBlock = block.number - 500;
        for (const [num] of blockHistory) {
          if (num < minBlock) blockHistory.delete(num);
        }
      }
    }
  }, 2000);
}
```

### 3. Block-Triggered Task Scheduler

Execute tasks whenever a new block is produced:

```javascript
async function onNewBlock(provider, callback) {
  const filterId = await provider.send('eth_newBlockFilter', []);

  const poll = async () => {
    try {
      const hashes = await provider.send('eth_getFilterChanges', [filterId]);
      for (const hash of hashes) {
        await callback(hash);
      }
    } catch (error) {
      if (error.message.includes('filter not found')) {
        return provider.send('eth_newBlockFilter', []).then(newId => {
          console.log('Block filter recreated');
          return newId;
        });
      }
      throw error;
    }
    return filterId;
  };

  let currentFilterId = filterId;
  setInterval(async () => {
    currentFilterId = await poll() || currentFilterId;
  }, 2000);
}

// Usage
onNewBlock(provider, async (blockHash) => {
  console.log(`Processing block: ${blockHash}`);
  // Run indexer, check conditions, send notifications, etc.
});
```

## Related Methods

- [`eth_getFilterChanges`](https://www.dwellir.com/docs/xdc-network/eth_getFilterChanges) - Poll this filter for new block hashes
- [`eth_uninstallFilter`](https://www.dwellir.com/docs/xdc-network/eth_uninstallFilter) - Remove the block filter when no longer needed
- [`eth_blockNumber`](https://www.dwellir.com/docs/xdc-network/eth_blockNumber) - Get the current block number (alternative to filter-based monitoring)
- [`eth_getBlockByHash`](https://www.dwellir.com/docs/xdc-network/eth_getBlockByHash) - Fetch full block details for hashes returned by the filter
