Docs

eth_newPendingTransactionFilter - Unichain RPC Method

Create a filter for pending transaction notifications on Unichain. Essential for mempool monitoring, transaction tracking, and MEV opportunity detection for decentralized exchanges, liquidity protocols, and MEV-protected DeFi applications.

Creates a filter on Unichain that notifies when new pending transactions are added to the mempool. Once created, poll the filter with eth_getFilterChanges to receive an array of transaction hashes for pending transactions that have appeared since your last poll.

Why Unichain? Build on Uniswap's DeFi-optimized Superchain L2 with 250ms sub-blocks and 95% lower costs than Ethereum with 250ms sub-blocks (fastest L2), TEE-secured block building, native Superchain interoperability, and 65% revenue to validators.

When to Use This Method

eth_newPendingTransactionFilter is essential for DeFi developers, liquidity protocol builders, and teams building on the Optimism Superchain:

  • Mempool Monitoring — Observe unconfirmed transactions on Unichain to understand network activity and congestion
  • Transaction Tracking — Detect when a specific transaction enters the mempool before it is mined
  • MEV Opportunity Detection — Identify arbitrage, liquidation, or sandwich opportunities by watching pending transactions
  • Gas Price Estimation — Analyze pending transactions to estimate optimal gas pricing for decentralized exchanges, liquidity protocols, and MEV-protected DeFi applications

Code Examples

Common Use Cases

1. Mempool Activity Dashboard

Monitor mempool throughput and transaction types on Unichain:

JavaScript
async function mempoolDashboard(provider) {
  const filterId = await provider.send('eth_newPendingTransactionFilter', []);

  const stats = {
    totalSeen: 0,
    contractCalls: 0,
    transfers: 0,
    intervalStart: Date.now()
  };

  setInterval(async () => {
    const txHashes = await provider.send('eth_getFilterChanges', [filterId]);
    stats.totalSeen += txHashes.length;

    for (const hash of txHashes) {
      try {
        const tx = await provider.getTransaction(hash);
        if (!tx) continue;

        if (tx.data && tx.data !== '0x') {
          stats.contractCalls++;
        } else {
          stats.transfers++;
        }
      } catch (e) {
        // Transaction may have been mined or dropped
      }
    }

    const elapsed = (Date.now() - stats.intervalStart) / 1000;
    const txPerSec = (stats.totalSeen / elapsed).toFixed(1);
    console.log(`Mempool: ${stats.totalSeen} txs (${txPerSec}/s) | Calls: ${stats.contractCalls} | Transfers: ${stats.transfers}`);
  }, 2000);
}

2. Track Specific Address Activity

Watch for pending transactions involving a target address:

JavaScript
async function watchAddress(provider, targetAddress) {
  const filterId = await provider.send('eth_newPendingTransactionFilter', []);
  const target = targetAddress.toLowerCase();

  console.log(`Watching pending transactions for ${targetAddress}...`);

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

    for (const hash of txHashes) {
      try {
        const tx = await provider.getTransaction(hash);
        if (!tx) continue;

        const isFrom = tx.from?.toLowerCase() === target;
        const isTo = tx.to?.toLowerCase() === target;

        if (isFrom || isTo) {
          console.log(`Pending tx detected for ${targetAddress}:`);
          console.log(`  Hash: ${hash}`);
          console.log(`  Direction: ${isFrom ? 'OUTGOING' : 'INCOMING'}`);
          console.log(`  Value: ${tx.value} wei`);
          console.log(`  Gas price: ${tx.gasPrice} wei`);
        }
      } catch (e) {
        // Transaction already mined or dropped
      }
    }
  }, 1000);
}

3. Large Transaction Alert System

Detect high-value pending transactions:

JavaScript
async function largeTransactionAlerts(provider, thresholdEth = 10) {
  const filterId = await provider.send('eth_newPendingTransactionFilter', []);
  const thresholdWei = BigInt(thresholdEth * 1e18);

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

    for (const hash of txHashes) {
      try {
        const tx = await provider.getTransaction(hash);
        if (!tx || !tx.value) continue;

        if (BigInt(tx.value) >= thresholdWei) {
          const ethValue = Number(BigInt(tx.value)) / 1e18;
          console.log(`LARGE TX: ${ethValue.toFixed(4)} ETH`);
          console.log(`  From: ${tx.from}`);
          console.log(`  To: ${tx.to}`);
          console.log(`  Hash: ${hash}`);
        }
      } catch (e) {
        // Transaction may have already been mined
      }
    }
  }, 1000);
}

Error Handling

Common errors and solutions:

Error CodeDescriptionSolution
-32603Internal errorNode may not expose mempool data — check node configuration
-32000Filter not foundFilter expired (~5 min inactivity) — recreate with eth_newPendingTransactionFilter
-32005Rate limit exceededReduce polling frequency — mempool can be very active
-32601Method not foundNode does not support pending transaction filters — requires a full node with txpool enabled
JavaScript
async function createPendingTxFilter(provider) {
  try {
    const filterId = await provider.send('eth_newPendingTransactionFilter', []);
    return { supported: true, filterId };
  } catch (error) {
    if (error.code === -32601 || error.message.includes('not found')) {
      console.warn('Pending transaction filter not supported by this node');
      console.warn('This method requires a full node with txpool access');
      return { supported: false };
    }
    throw error;
  }
}