Building a Paymaster Liquidity Monitor for ERC-4337 using the GoldRush API - Part 2

Zeeshan Jawed
Content Writer
Build the "UserOp Traffic Controller". Monitor real-time Paymaster interactions, analyze gas usage, and detect spikes using the GoldRush Wallet Activity API

Introduction: Monitoring the Burn Rate

In Part 1, we built a "Fuel Gauge" to monitor the static balance of our Paymaster wallet. This prevents the tank from running dry. But efficient operations require more than just watching the needle; they require understanding the consumption.

In the ERC-4337 ecosystem, the Paymaster is a high-activity contract. Every time a user interacts with your dApp, the Bundler calls the handleOps function on the EntryPoint, which in turn calls validatePaymasterUserOp on your Paymaster.

If you see your balance dropping rapidly, you need to know:

  • Who is sending these UserOps?

  • When did the spike occur?

  • Which specific function calls are being sponsored?

In Part 2, we will build an Activity Agent. We will use the GoldRush Wallet Activity API to stream and analyze the historical and real-time event logs of our Paymaster contract.

Chapter 1: The Data Source – Wallet Activity API

The GoldRush Address Activity endpoint is uniquely suited for this task. Unlike standard block explorers that just show "Transactions," this API parses the Log Events emitted by the contract.

For a Paymaster, the most critical signal isn't always a direct transaction (since UserOps are meta-transactions wrapped by Bundlers). The signal is in the Logs.

We are looking for specific interactions:

  1. Incoming UserOps: Usually identifiable by calls from the EntryPoint contract.

  2. Deposits: When the Paymaster adds funds to the EntryPoint.

  3. Withdrawals: When the admin removes funds.

Chapter 2: Building the Activity Analyzer

We will extend our project from Part 1. Create a new file src/activity.ts.

The Goal

Fetch the last 100 interactions involving the Paymaster and categorize them

import { GoldRushClient } from "@covalenthq/client-sdk"; import * as dotenv from "dotenv"; dotenv.config(); const API_KEY = process.env.GOLDRUSH_API_KEY!; const PAYMASTER = process.env.PAYMASTER_ADDRESS!; const CHAIN = process.env.CHAIN_NAME || "base-mainnet"; const client = new GoldRushClient(API_KEY); interface InteractionEvent { txHash: string; blockSignedAt: Date; label: string; gasSpent: number; feesPaid: number; } async function analyzePaymasterActivity() { console.log(`šŸ“” Scanning Activity for Paymaster: ${PAYMASTER}...`); try { // Fetch recent transactions for the Paymaster address const resp = await client.BaseService.getAddressActivity( CHAIN, PAYMASTER ); if (resp.error) { console.error("āŒ API Error:", resp.error_message); return; } const events: InteractionEvent[] = []; for (const item of resp.data.items) { // In ERC-4337, the 'from' address is usually the Bundler // The 'to' address is the EntryPoint // The Paymaster is involved via internal calls/logs let label = "Unknown Interaction"; // Simple heuristic labeling based on logs or method calls // Note: GoldRush provides decoded logs which makes this powerful if (item.category === "er20" || item.category === "nativetoken") { label = "Fund Transfer"; } else if (item.value_quote > 0) { label = "Value Transfer"; } else { label = "Contract Call (Likely UserOp)"; } events.push({ txHash: item.tx_hash, blockSignedAt: new Date(item.block_signed_at), label: label, gasSpent: item.gas_spent, feesPaid: item.fees_paid }); } return events; } catch (error) { console.error("Processing Error:", error); return []; } }

Chapter 3: Visualizing the Traffic

Now, let's process this data to generate a readable report. We want to see the frequency of operations.

Add this reporting logic to the script:

(async () => { const activityLog = await analyzePaymasterActivity(); if (activityLog && activityLog.length > 0) { console.log(`\nšŸ“Š ACTIVITY REPORT (Last ${activityLog.length} Txns)`); console.log("------------------------------------------------"); // 1. Calculate Burn Rate (Average Fee) const totalFees = activityLog.reduce((acc, curr) => acc + (curr.feesPaid || 0), 0); const avgFee = totalFees / activityLog.length; console.log(`šŸ”„ Total Fees Burned (Window): $${totalFees.toFixed(2)}`); console.log(`šŸ“‰ Avg Cost per Tx: $${avgFee.toFixed(4)}`); // 2. Recent Log console.log("\nšŸ“ Recent Interactions:"); activityLog.slice(0, 5).forEach(event => { console.log(`[${event.blockSignedAt.toISOString()}] ${event.label} | Gas: ${event.gasSpent} | Hash: ${event.txHash.slice(0, 10)}...`); }); } else { console.log("No recent activity found."); } })();

Chapter 4: Advanced Filtering (The "UserOp" Detective)

The generic activity feed shows everything. To specifically isolate UserOperations, we need to filter for transactions that interacted with the EntryPoint Contract.

Typically, the Paymaster is not the direct recipient of a transaction. The Bundler calls EntryPoint.handleOps(). The EntryPoint then calls the Paymaster.

To see this specifically, we can use the GoldRush Log Events endpoint (getLogEventsByContract) filtering for the UserOperationEvent emitted by the EntryPoint, but filtered where the Paymaster is a topic (if the event structure allows) or simply correlating the transactions.

For a lightweight agent, a robust heuristic is checking if the transaction was sent to the known EntryPoint Address (0x5FF1...)

// Refined Logic inside the loop const ENTRY_POINT = "0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789"; if (item.to_address === ENTRY_POINT) { label = "⚔ Sponsored UserOp"; }

By adding this check, your logs will clearly differentiate between "Admin Maintenance" (refilling funds) and "User Traffic" (sponsored UserOps)

Conclusion: The Complete Picture

You have now built a dual-layer monitoring system for your ERC-4337 infrastructure.

  1. Part 1 (Fuel Gauge): Monitors the Paymaster's wallet balance using TokenBalances. It ensures you never run out of liquidity.

  2. Part 2 (Traffic Controller): Monitors the Paymaster's interactions using WalletActivity. It calculates burn rate and identifies UserOp volume.

Next Steps for Production:

  • Dockerize: Containerize these scripts to run as persistent agents.

  • Database: Pipe the activity logs into a TimescaleDB or Postgres database to build long-term dashboards (Grafana).

  • Alerting: Connect the "Critical Low Fuel" logic to a PagerDuty API to wake up your DevOps team before users notice a failure.

With GoldRush, you have turned the opaque "Black Box" of Account Abstraction into a transparent, observable system.

Get Started

Get started with GoldRush API in minutes. Sign up for a free API key and start building.

Support

Explore multiple support options! From FAQs for self-help to real-time interactions on Discord.

Contact Sales

Interested in our professional or enterprise plans? Contact our sales team to learn more.