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

Zeeshan Jawed
Content Writer
Build the "Fuel Gauge" for Account Abstraction. Monitor Paymaster balances and prevent gas failures using Covalent GoldRush

Introduction: The Hidden Risk of Account Abstraction

\ERC-4337 (Account Abstraction) has revolutionized the Ethereum user experience. By introducing Smart Accounts and Paymasters, we have enabled gasless transactions, social recovery, and batched operations. Apps can now sponsor users' gas fees, making Web3 feel like Web2.

But this magic comes with a hidden operational risk: Liquidity Management.

A Paymaster is essentially a gas tank. It holds ETH (or the native chain token) and uses it to reimburse the Bundler for executing UserOperations. If that gas tank runs empty, the entire application grinds to a halt. Transactions fail, users get frustrated, and the "magical" UX breaks.

In Part 1 of this series, we will build the "Fuel Gauge" for your AA infrastructure. We will create a Paymaster Liquidity Monitor using the Covalent GoldRush API. This agent will:

  1. Continuously track the native balance of your Paymaster wallet.

  2. Understand the difference between "Wallet Balance" and "EntryPoint Deposit."

  3. Trigger alerts when liquidity drops below a critical threshold.

Chapter 1: The Anatomy of a Paymaster

Before we write code, we must understand where the money lives. In ERC-4337, a Paymaster handles funds in two distinct places:

  1. The EntryPoint Deposit: This is the actual gas tank. The Paymaster contract must deposit native tokens (ETH/MATIC/AVAX) into the global EntryPoint contract. The Bundler deducts gas costs directly from this internal balance during UserOp execution.

  2. The Paymaster EOA/Wallet: This is the "Refill Truck." It is the external wallet or contract balance that holds the reserve funds before they are deposited into the EntryPoint.

The Monitoring Strategy:

While tracking the EntryPoint deposit requires reading contract state (often via RPC calls), tracking the Paymaster's Wallet Balance is the first line of defense. If the wallet is empty, the Paymaster cannot refill the EntryPoint.

We will use the GoldRush Token Balances API to monitor this reserve balance.

Chapter 2: Project Setup

We will build a lightweight Node.js service.

Prerequisites

  • Node.js v18+

  • A Covalent API Key (Get it from GoldRush.dev)

  • A target Paymaster address (We can use a known public Paymaster on Base or Polygon for testing)

Initialization

Add this to your CLI:

mkdir paymaster-monitor cd paymaster-monitor npm init -y npm install @covalenthq/client-sdk dotenv typescript ts-node @types/node npx tsc --init

Create your .env file:

GOLDRUSH_API_KEY=your_covalent_api_key # Example: A generic Paymaster address on Base PAYMASTER_ADDRESS=0x00000f79b7152151b3741c0f190294741938a9b9 CHAIN_NAME=base-mainnet LOW_BALANCE_THRESHOLD=0.5

Chapter 3: Fetching Paymaster Balances

We will use the BalanceService from the GoldRush SDK. This endpoint is highly optimized for retrieving the complete portfolio of an address, but for a Paymaster, we specifically care about the Native Token (Gas Token).

Create src/monitor.ts:

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 THRESHOLD = parseFloat(process.env.LOW_BALANCE_THRESHOLD || "0.1"); const client = new GoldRushClient(API_KEY); interface BalanceReport { address: string; chain: string; nativeBalance: number; quoteBalance: number; // USD Value isCritical: boolean; } async function checkPaymasterHealth(): Promise<BalanceReport | null> { console.log(`šŸ” Checking Paymaster Fuel: ${PAYMASTER} on ${CHAIN}...`); try { const resp = await client.BalanceService.getTokenBalancesForWalletAddress( CHAIN, PAYMASTER ); if (resp.error) { console.error("āŒ API Error:", resp.error_message); return null; } // Filter for the Native Token (e.g., ETH on Base, MATIC on Polygon) // The SDK usually marks native tokens with `native_token: true` const nativeToken = resp.data.items.find(item => item.native_token); if (!nativeToken) { console.error("āš ļø No native token found in wallet!"); return null; } // Convert raw balance (BigInt string) to decimal // Formula: balance / 10^decimals const rawBalance = BigInt(nativeToken.balance); const decimals = nativeToken.contract_decimals; const formattedBalance = Number(rawBalance) / Math.pow(10, decimals); const report: BalanceReport = { address: PAYMASTER, chain: CHAIN, nativeBalance: formattedBalance, quoteBalance: nativeToken.quote || 0, isCritical: formattedBalance < THRESHOLD }; return report; } catch (error) { console.error("šŸ’€ Fatal Error:", error); return null; } } // --- Execution Block --- (async () => { const health = await checkPaymasterHealth(); if (health) { console.log("\nšŸ“Š PAYMASTER HEALTH REPORT"); console.log("---------------------------"); console.log(`⛽ Native Balance: ${health.nativeBalance.toFixed(4)} ETH`); console.log(`šŸ’µ USD Value: $${health.quoteBalance.toFixed(2)}`); console.log(`🚨 Status: ${health.isCritical ? "CRITICAL LOW FUEL" : "HEALTHY"}`); if (health.isCritical) { // Placeholder for alerting logic (PagerDuty / Slack) console.log(">>> TRIGGERING REFILL ALERT <<<"); } } })();

Chapter 4: Running the Monitor

Run the script to verify your connection to the GoldRush API.

npx ts-node src/monitor.ts

Expected Output

This simple output is powerful. It gives you an instant snapshot of your Paymaster's ability to fund operations.

Chapter 5: Extending to Multi-Chain

Account Abstraction is inherently multi-chain. A dApp deployed on Base, Optimism, and Arbitrum needs Paymasters on all three.

The GoldRush SDK simplifies this. We can wrap our logic in a loop.

const CHAINS = ["base-mainnet", "optimism-mainnet", "arbitrum-mainnet"]; async function checkFleet() { for (const chain of CHAINS) { // We assume the Paymaster address is the same (deterministic deployment) // or mapped via configuration const health = await checkPaymasterHealth(chain, PAYMASTER); // ... Log logic ... } }

Conclusion: The First Line of Defense

We have successfully built the "Fuel Gauge." We are monitoring the reserve liquidity that keeps the Paymaster running. However, knowing how much gas you have is only half the battle. You also need to know how fast you are burning it.

Is your Paymaster draining 0.1 ETH per day, or did it suddenly drain 5 ETH in an hour due to a bot spamming UserOps? To answer that, we need Activity Tracking.

In Part 2, we will build the "UserOp Traffic Controller." We will use the GoldRush Wallet Activity API to monitor the actual interactions with the Paymaster contract, allowing us to detect spikes, analyze gas usage patterns, and spot potential exploits in real-time.

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.