Skip to content

[Bug] Client-side components use server publicClient — 429 rate limits on browser RPC calls #389

@realproject7

Description

@realproject7

Summary

Multiple client-side components import publicClient from lib/rpc.ts, which uses the server-side fallback transport (no CORS headers). In the browser, these calls fall back to the default chain RPC (mainnet.base.org), bypassing the CORS-safe fallback rotation and causing 429 rate limits.

Screenshot shows TradingWidget.tsx:61 and RatingWidget.tsx:61 hitting mainnet.base.org directly with 429 errors.

Root Cause

lib/rpc.ts exports one publicClient built with buildServerTransport(). This works on the server (API routes) but not in the browser — the browser needs CORS headers. The CORS-safe transport exists (createFallbackTransport()) but is only used for wagmi config, not for direct publicClient.readContract() calls in components.

Affected Components (browser-side, use publicClient.readContract())

File Line Call
src/components/TradingWidget.tsx 61 getReserveForToken / getRefundForTokens (price estimate)
src/components/RatingWidget.tsx 61 balanceOf (token balance check)
src/components/DonateWidget.tsx 38, 60, 75, 90 allowance, balanceOf, waitForTransactionReceipt
src/components/ClaimRoyalties.tsx 40, 95 getRoyaltyInfo, waitForTransactionReceipt
src/components/ReaderPortfolio.tsx 48, 64 multicall, readContract
src/components/WriterTradingStats.tsx 23 readContract
src/app/create/page.tsx 93 creationFee read
src/app/dashboard/reader/page.tsx 64 readContract

Fix

Option A: Export a browser-safe public client (recommended)

Add to lib/rpc.ts:

/**
 * Browser-safe public client with CORS fallback.
 * Use this in client components ("use client") instead of publicClient.
 */
export const browserClient = createPublicClient({
  chain,
  transport: IS_MAINNET ? createFallbackTransport() : (CUSTOM_RPC_URL ? fallback([http(CUSTOM_RPC_URL), http()]) : http()),
});

Then update all affected components to import browserClient instead of publicClient.

Option B: Use wagmi's useReadContract hook

Replace direct publicClient.readContract() calls with wagmi's useReadContract hook, which already uses the CORS-safe transport from wagmi config.

Recommendation

Option A is simpler — one new export, find-and-replace in 8 files. Option B would be a larger refactor touching the data fetching patterns.

Server-side files (NO change needed)

These correctly use the server-side publicClient:

  • src/app/api/index/* (all API routes)
  • src/app/api/cron/* (cron routes)
  • src/app/api/ratings/route.ts
  • lib/price.ts
  • lib/contracts/erc8004.ts
  • scripts/backfill-trade-prices.ts

Acceptance Criteria

  • Browser-side components use CORS-safe fallback transport
  • No more direct mainnet.base.org 429 errors in browser console
  • Server-side API routes continue using existing publicClient (no change)
  • npm run typecheck passes
  • npm run lint passes

Branch

task/{issue-number}-browser-rpc-fallback

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/T3Assigned to T3 builder agentbugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions