Skip to content

Conversation

@joaquim-verges
Copy link
Member

@joaquim-verges joaquim-verges commented Sep 15, 2025

[Dashboard] Feature: Add EIP-7702 Support detection to Chain Overview

AI-32

Notes for the reviewer

This PR replaces the "Block Gas Limit" stat in the Chain Overview card with "EIP-7702 Support".

  • A new useEIP7702Support hook was created to detect support by sending a specific eth_estimateGas RPC request, as outlined in the task.
  • The RPC call is made to the chain's RPC URL, adapting for dev/prod environments.
  • If the RPC call returns a valid result, EIP-7702 is considered "Enabled" (green badge); otherwise, it's "Disabled" (red badge).
  • The query is configured not to refetch, as EIP-7702 support is a static chain property.

How to test

  1. Navigate to any chain page in the dashboard (e.g., /dashboard/avalanche-c).
  2. Observe the "Chain Overview" card.
  3. Verify that "EIP-7702 Support" is displayed instead of "Block Gas Limit".
  4. Check a chain known to support EIP-7702 (e.g., Avalanche C-Chain) to confirm the "Enabled" badge.
  5. Check a chain not supporting EIP-7702 (or one where the RPC call would fail) to confirm the "Disabled" badge.

Slack Thread

Open in Cursor Open in Web

PR-Codex overview

This PR focuses on enhancing the ChainLiveStats component by adding support for EIP-7702 and refactoring existing code to remove the block gas limit display. It introduces a new function to check EIP-7702 support via RPC and updates the UI accordingly.

Detailed summary

  • Removed blockGasLimit from the return object.
  • Added useEIP7702Support function to check EIP-7702 support via RPC.
  • Updated ChainLiveStats to include EIP-7702 support status.
  • Changed "Block Height" to "Latest Block" in the UI.
  • Displayed EIP-7702 status with appropriate icons and labels.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features

    • Added an EIP-7702 status indicator in Chain Live Stats with Enabled/Disabled badges, error-disabled state, and a loading placeholder.
  • Style

    • Renamed “Block Height” to “Latest Block”.
    • Replaced the Block Gas Limit section with the new EIP-7702 section.
    • Improved loading states with adjusted skeleton widths (Latest Block: 140px, EIP-7702: 80px).
  • Chores

    • Internal RPC handling and EIP-7702 detection updated; public component signature unchanged.

@cursor
Copy link

cursor bot commented Sep 15, 2025

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@changeset-bot
Copy link

changeset-bot bot commented Sep 15, 2025

⚠️ No Changeset found

Latest commit: 4bf256f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Sep 15, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
thirdweb-www Ready Ready Preview Comment Sep 16, 2025 0:40am
4 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
docs-v2 Skipped Skipped Sep 16, 2025 0:40am
nebula Skipped Skipped Sep 16, 2025 0:40am
thirdweb_playground Skipped Skipped Sep 16, 2025 0:40am
wallet-ui Skipped Skipped Sep 16, 2025 0:40am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 15, 2025

Walkthrough

Adds EIP-7702 support detection to ChainLiveStats via a new internal hook that probes RPCs with an eth_estimateGas call, normalizes RPC URLs, updates UI labels, replaces Block Gas Limit with an EIP-7702 status section, and tweaks skeleton widths. No public API signature changes.

Changes

Cohort / File(s) Summary
Chain live stats + EIP-7702 probe
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
- Remove blockGasLimit from useChainStatswithRPC return
- Add useEIP7702Support(_rpcUrl) hook: normalize RPC URL (inject NEXT_PUBLIC_DASHBOARD_CLIENT_ID), rewrite rpc.thirdweb.comrpc.thirdweb-dev.com in non-prod, call JSON-RPC eth_estimateGas, return boolean via useQuery keyed ["eip-7702-support", { rpcUrl }], do not refetch on window focus, errors yield false
- ChainLiveStats uses new hook
- UI: rename “Block Height” → “Latest Block”; replace “Block Gas Limit” with “EIP-7702” section showing Enabled/Disabled/Loading (skeleton width 80px); adjust Latest Block skeleton loading width to 140px; import/use Badge for status UI

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant C as ChainLiveStats
  participant H as useEIP7702Support
  participant N as RPC Normalizer
  participant R as RPC Endpoint
  participant Q as React Query

  U->>C: Open chain page
  C->>H: init with rpc
  H->>N: normalize rpc URL (inject clientId, env redirect)
  N-->>H: normalizedRpc
  H->>Q: query(["eip-7702-support",{rpcUrl}])
  alt cached
    Q-->>H: isSupported
  else
    H->>R: JSON-RPC eth_estimateGas
    alt success
      R-->>H: result
      H-->>Q: store true/false
    else error
      R--x H: error
      H-->>Q: store false
    end
    Q-->>H: isSupported
  end
  H-->>C: {isSupported, isLoading, isError}
  C-->>U: render EIP-7702 badge/skeleton and Latest Block
  note over H,Q: query key ["eip-7702-support",{rpcUrl}] — no refetchOnWindowFocus
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title Check ✅ Passed The title "[Dashboard] Display eip7702 support status" is concise and accurately reflects the primary change in the PR — adding/displaying EIP-7702 support in the Dashboard chain overview — so it correctly summarizes the main intent of the changeset.
Linked Issues Check ✅ Passed The changes implement the linked issue AI-32 by adding an RPC-based EIP-7702 detection hook, wiring the result into the Chain Overview UI, and treating support as a static chain property as requested, so the coding objectives align with the issue.
Out of Scope Changes Check ✅ Passed The summarized diffs are limited to replacing the Block Gas Limit stat with EIP-7702 detection, renaming "Block Height" to "Latest Block", and small UI/skeleton adjustments, all of which are directly related to the linked issue and do not introduce unrelated or out-of-scope functionality.
Description Check ✅ Passed The PR description follows the repository template by including the issue tag (AI-32), a clear "Notes for the reviewer" section describing the implementation, and a "How to test" section with explicit manual test steps, making it actionable and mostly complete for reviewers.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cursor/display-eip7702-support-status-cd7c

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3261dec and 4bf256f.

📒 Files selected for processing (1)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: Size
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • EIP-7702: Entity not found: Issue - Could not find referenced Issue.

Comment @coderabbitai help to get the list of available commands and usage tips.

@graphite-app
Copy link
Contributor

graphite-app bot commented Sep 15, 2025

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • merge-queue - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

@github-actions github-actions bot added the Dashboard Involves changes to the Dashboard. label Sep 15, 2025
@codecov
Copy link

codecov bot commented Sep 15, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 56.51%. Comparing base (210f631) to head (4bf256f).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8060   +/-   ##
=======================================
  Coverage   56.51%   56.51%           
=======================================
  Files         904      904           
  Lines       58865    58865           
  Branches     4170     4170           
=======================================
  Hits        33269    33269           
  Misses      25491    25491           
  Partials      105      105           
Flag Coverage Δ
packages 56.51% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Contributor

github-actions bot commented Sep 15, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 63.96 KB (-0.11% 🔽) 1.3 s (-0.11% 🔽) 310 ms (+34.52% 🔺) 1.6 s
thirdweb (cjs) 361.44 KB (0%) 7.3 s (0%) 2 s (+2.29% 🔺) 9.3 s
thirdweb (minimal + tree-shaking) 5.73 KB (0%) 115 ms (0%) 95 ms (+771.68% 🔺) 209 ms
thirdweb/chains (tree-shaking) 526 B (0%) 11 ms (0%) 50 ms (+499.36% 🔺) 60 ms
thirdweb/react (minimal + tree-shaking) 19.15 KB (0%) 383 ms (0%) 66 ms (+445.92% 🔺) 449 ms

@vercel vercel bot temporarily deployed to Preview – nebula September 15, 2025 23:42 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 September 15, 2025 23:42 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground September 15, 2025 23:42 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui September 15, 2025 23:42 Inactive
@joaquim-verges joaquim-verges marked this pull request as ready for review September 15, 2025 23:51
@joaquim-verges joaquim-verges requested review from a team as code owners September 15, 2025 23:51
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx (4)

63-122: Harden the 7702 probe: type return, add headers/timeout, handle JSON‑RPC errors, and cache long.

  • Add explicit return type for the hook.
  • Send Content-Type header and use an AbortController timeout to avoid hanging queries.
  • Treat JSON-RPC error objects explicitly; check result type is hex string.
  • Since support is static, set a long staleTime and disable retries; optionally extend cache/gc time.

Apply:

-function useEIP7702Support(_rpcUrl: string) {
+import type { UseQueryResult } from "@tanstack/react-query";
+
+function useEIP7702Support(_rpcUrl: string): UseQueryResult<{ isSupported: boolean }, unknown> {
   let rpcUrl = _rpcUrl.replace(
@@
   return useQuery({
     enabled: !!rpcUrl,
     queryFn: async () => {
-      try {
-        const res = await fetch(rpcUrl, {
-          body: JSON.stringify({
+      const controller = new AbortController();
+      const timer = setTimeout(() => controller.abort(), 12_000);
+      try {
+        const res = await fetch(rpcUrl, {
+          headers: { "Content-Type": "application/json" },
+          body: JSON.stringify({
             id: 1,
             jsonrpc: "2.0",
             method: "eth_estimateGas",
             params: [
               {
                 from: "0xdeadbeef00000000000000000000000000000000",
                 to: "0xdeadbeef00000000000000000000000000000000",
                 data: "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
                 value: "0x0"
               },
               "latest",
               {
                 "0xdeadbeef00000000000000000000000000000000": {
                   code: "0xef01000000000000000000000000000000000000000001"
                 }
               }
             ],
           }),
           method: "POST",
+          signal: controller.signal,
         });
 
-        const json = await res.json();
-        
-        // If the response has a valid result object, EIP-7702 is enabled
-        return {
-          isSupported: !!json.result,
-        };
+        const json: { result?: unknown; error?: unknown } = await res.json();
+        const okHex = typeof json.result === "string" && /^0x[0-9a-f]+$/i.test(json.result);
+        if (!res.ok || json && "error" in json) {
+          return { isSupported: false };
+        }
+        return { isSupported: okHex };
       } catch {
         // If the request fails or errors, EIP-7702 is not supported
         return {
           isSupported: false,
         };
       }
+      finally {
+        clearTimeout(timer);
+      }
     },
     queryKey: ["eip-7702-support", { rpcUrl }],
-    refetchInterval: false, // Don't refetch this as it's unlikely to change
+    refetchInterval: false, // static per chain
+    staleTime: 24 * 60 * 60 * 1000,
+    retry: false,
     refetchOnWindowFocus: false,
   });
 }

63-77: Deduplicate RPC URL normalization into a small util.

Both hooks repeat the same env/clientId logic. Extract to avoid drift.

Add:

// helper (place near top of file or shared util)
function normalizeRpcUrlForEnv(raw: string): string {
  let url = raw.replace("${THIRDWEB_API_KEY}", NEXT_PUBLIC_DASHBOARD_CLIENT_ID);
  if (hostnameEndsWith(url, "rpc.thirdweb.com") && !isProd) {
    url = url.replace("rpc.thirdweb.com", "rpc.thirdweb-dev.com");
  }
  return url;
}

Then change:

- let rpcUrl = _rpcUrl.replace( /* ... */ );
- // env switch ...
+ const rpcUrl = normalizeRpcUrlForEnv(_rpcUrl);

You can optionally apply the same to useChainStatswithRPC for consistency.


171-173: Format block number for readability.

Thousand separators improve scanability without changing meaning.

-  <p className="fade-in-0 animate-in">{stats.data.blockNumber}</p>
+  <p className="fade-in-0 animate-in">{stats.data.blockNumber.toLocaleString()}</p>

184-197: Consider not conflating network errors with “Disabled”.

If the RPC is down, labeling as “Disabled” may be misleading. Optional: show “Unknown” with a neutral badge on isError.

- {eip7702Support.isError ? (
-   <Badge variant="destructive">Disabled</Badge>
- ) : eip7702Support.data ? (
+ {eip7702Support.isError ? (
+   <Badge variant="secondary">Unknown</Badge>
+ ) : eip7702Support.data ? (
    <Badge variant={eip7702Support.data.isSupported ? "success" : "destructive"}>
      {eip7702Support.data.isSupported ? "Enabled" : "Disabled"}
    </Badge>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 210f631 and e761f82.

📒 Files selected for processing (1)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx (4 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose

**/*.{ts,tsx}: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from @/types where applicable
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size

Files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)

Files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/* (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Use NavLink for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Use cn() from @/lib/utils for conditional class logic
Use design system tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components (Node edge): Start files with import "server-only";
Client Components (browser): Begin files with 'use client';
Always call getAuthToken() to retrieve JWT from cookies on server side
Use Authorization: Bearer header – never embed tokens in URLs
Return typed results (e.g., Project[], User[]) – avoid any
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stable queryKeys for React Query cache hits
Configure staleTime/cacheTime in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never import posthog-js in server components

Files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
apps/{dashboard,playground}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

apps/{dashboard,playground}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/_ (e.g., Button, Input, Tabs, Card)
Use NavLink for internal navigation to get active state handling
Use Tailwind CSS for styling; no inline styles
Merge class names with cn() from @/lib/utils for conditional classes
Stick to design tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components must start with import "server-only"; use next/headers, server‑only env, heavy data fetching, and redirect() where appropriate
Client Components must start with 'use client'; handle interactivity with hooks and browser APIs
Server-side data fetching: call getAuthToken() from cookies, send Authorization: Bearer <token> header, and return typed results (avoid any)
Client-side data fetching: wrap calls in React Query with descriptive, stable queryKeys and set sensible staleTime/cacheTime (≥ 60s default); keep tokens secret via internal routes or server actions
Do not import posthog-js in server components (client-side only)

Files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
apps/{dashboard,playground}/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Expose a className prop on the root element of every component

Files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
🧠 Learnings (8)
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Components that listen to user events, animations or live updates.

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Use React Query (`tanstack/react-query`) for all client data fetching.

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to apps/{dashboard,playground}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/_` (e.g., Button, Input, Tabs, Card)

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Prefer composable primitives over custom markup: `Button`, `Input`, `Select`, `Tabs`, `Card`, `Sidebar`, `Separator`, `Badge`.

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Wrap client-side data fetching calls in React Query (`tanstack/react-query`)

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
🧬 Code graph analysis (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx (2)
apps/dashboard/src/@/constants/public-envs.ts (1)
  • NEXT_PUBLIC_DASHBOARD_CLIENT_ID (1-2)
apps/dashboard/src/@/constants/env-utils.ts (1)
  • isProd (1-3)
🔇 Additional comments (3)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx (3)

5-5: Correct UI import path for Badge.

Matches dashboard UI import guidelines. No issues.


126-126: Hook usage looks good.

Query key is stable via rpcUrl, and the UI handles loading/error states.


184-191: Verify Badge supports variant="success".

If the Badge variants are limited to default/secondary/destructive/outline, “success” will render incorrectly.

Would you confirm the Badge variant union? If needed, swap to variant="default" and add className="bg-success text-success-foreground" via tokens.

@joaquim-verges joaquim-verges changed the title Display eip7702 support status [Dashboard] Display eip7702 support status Sep 16, 2025
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground September 16, 2025 00:24 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 September 16, 2025 00:24 Inactive
@vercel vercel bot temporarily deployed to Preview – nebula September 16, 2025 00:24 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui September 16, 2025 00:24 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx (2)

63-77: Deduplicate RPC URL normalization

This logic duplicates Lines 15–27. Extract a shared helper to avoid drift between hooks.

Apply within this range:

-function useEIP7702Support(_rpcUrl: string) {
-  let rpcUrl = _rpcUrl.replace(
-    // eslint-disable-next-line no-template-curly-in-string
-    // biome-ignore lint/suspicious/noTemplateCurlyInString: this is expected in this case
-    "${THIRDWEB_API_KEY}",
-    NEXT_PUBLIC_DASHBOARD_CLIENT_ID,
-  );
-
-  // based on the environment hit dev or production
-  if (hostnameEndsWith(rpcUrl, "rpc.thirdweb.com")) {
-    if (!isProd) {
-      rpcUrl = rpcUrl.replace("rpc.thirdweb.com", "rpc.thirdweb-dev.com");
-    }
-  }
+function useEIP7702Support(_rpcUrl: string) {
+  const rpcUrl = normalizeRpcUrlForDashboard(_rpcUrl);

Add once (outside this hunk), near the top of the file:

function normalizeRpcUrlForDashboard(url: string): string {
  let rpcUrl = url.replace(
    "${THIRDWEB_API_KEY}",
    NEXT_PUBLIC_DASHBOARD_CLIENT_ID,
  );
  if (hostnameEndsWith(rpcUrl, "rpc.thirdweb.com") && !isProd) {
    rpcUrl = rpcUrl.replace("rpc.thirdweb.com", "rpc.thirdweb-dev.com");
  }
  return rpcUrl;
}

78-122: Harden query: headers, abort, typing, and cache policy

  • Send Content-Type header and respect React Query abort signal.
  • Treat non-2xx as errors; check for json.error.
  • Add sensible staleTime (static property) and explicit return type.

Apply within this range:

-  return useQuery({
+  return useQuery({
     enabled: !!rpcUrl,
-    queryFn: async () => {
+    queryFn: async ({ signal }) => {
       try {
-        const res = await fetch(rpcUrl, {
+        const res = await fetch(rpcUrl, {
           body: JSON.stringify({
             id: 1,
             jsonrpc: "2.0",
             method: "eth_estimateGas",
             params: [
               {
                 from: "0xdeadbeef00000000000000000000000000000000",
                 to: "0xdeadbeef00000000000000000000000000000000",
                 data: "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
                 value: "0x0",
               },
               "latest",
               {
                 "0xdeadbeef00000000000000000000000000000000": {
                   code: "0xef01000000000000000000000000000000000000000001",
                 },
               },
             ],
           }),
           method: "POST",
+          headers: { "Content-Type": "application/json" },
+          signal,
         });
 
-        const json = await res.json();
-
-        // If the response has a valid result object, EIP-7702 is enabled
-        return {
-          isSupported: !!json.result,
-        };
+        if (!res.ok) {
+          throw new Error(`RPC ${res.status}`);
+        }
+        const json: { result?: unknown; error?: unknown } = await res.json();
+        const hasResult = typeof json.result === "string";
+        return { isSupported: hasResult };
       } catch {
         // If the request fails or errors, EIP-7702 is not supported
         return {
           isSupported: false,
         };
       }
     },
     queryKey: ["eip-7702-support", { rpcUrl }],
-    refetchInterval: false, // Don't refetch this as it's unlikely to change
+    staleTime: 24 * 60 * 60 * 1000, // static per chain
+    refetchInterval: false, // Don't refetch this as it's unlikely to change
     refetchOnWindowFocus: false,
   });

Add explicit typing (outside this hunk):

- import { useQuery } from "@tanstack/react-query";
+ import { useQuery, type UseQueryResult } from "@tanstack/react-query";

And annotate the hook signature (within Line 63):

-function useEIP7702Support(_rpcUrl: string) {
+type EIP7702Support = { isSupported: boolean };
+function useEIP7702Support(_rpcUrl: string): UseQueryResult<EIP7702Support, Error> {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e761f82 and 3261dec.

📒 Files selected for processing (1)
  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx (4 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose

**/*.{ts,tsx}: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from @/types where applicable
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size

Files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)

Files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
apps/{dashboard,playground-web}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/{dashboard,playground-web}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/* (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Use NavLink for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Use cn() from @/lib/utils for conditional class logic
Use design system tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components (Node edge): Start files with import "server-only";
Client Components (browser): Begin files with 'use client';
Always call getAuthToken() to retrieve JWT from cookies on server side
Use Authorization: Bearer header – never embed tokens in URLs
Return typed results (e.g., Project[], User[]) – avoid any
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stable queryKeys for React Query cache hits
Configure staleTime/cacheTime in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never import posthog-js in server components

Files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
apps/{dashboard,playground}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

apps/{dashboard,playground}/**/*.{ts,tsx}: Import UI primitives from @/components/ui/_ (e.g., Button, Input, Tabs, Card)
Use NavLink for internal navigation to get active state handling
Use Tailwind CSS for styling; no inline styles
Merge class names with cn() from @/lib/utils for conditional classes
Stick to design tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components must start with import "server-only"; use next/headers, server‑only env, heavy data fetching, and redirect() where appropriate
Client Components must start with 'use client'; handle interactivity with hooks and browser APIs
Server-side data fetching: call getAuthToken() from cookies, send Authorization: Bearer <token> header, and return typed results (avoid any)
Client-side data fetching: wrap calls in React Query with descriptive, stable queryKeys and set sensible staleTime/cacheTime (≥ 60s default); keep tokens secret via internal routes or server actions
Do not import posthog-js in server components (client-side only)

Files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
apps/{dashboard,playground}/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Expose a className prop on the root element of every component

Files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
🧠 Learnings (7)
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Use React Query (`tanstack/react-query`) for all client data fetching.

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to apps/{dashboard,playground}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/_` (e.g., Button, Input, Tabs, Card)

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Prefer composable primitives over custom markup: `Button`, `Input`, `Select`, `Tabs`, `Card`, `Sidebar`, `Separator`, `Badge`.

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{ts,tsx} : Wrap client-side data fetching calls in React Query (`tanstack/react-query`)

Applied to files:

  • apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx
🧬 Code graph analysis (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx (2)
apps/dashboard/src/@/constants/public-envs.ts (1)
  • NEXT_PUBLIC_DASHBOARD_CLIENT_ID (1-2)
apps/dashboard/src/@/constants/env-utils.ts (1)
  • isProd (1-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Size
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx (4)

5-5: Good: design‑system Badge import

Matches dashboard UI guidelines; keeps primitives consistent.


126-126: Hook usage looks good

Stable queryKey and no refetch aligns with “static property” intent.


171-172: UI copy: LGTM

“Latest Block” is clearer than “Block Height.”


184-201: Badge 'success' variant is supported — no change required.
BadgeProps in apps/wallet-ui/src/components/ui/badge.tsx (and the nebula mirror) include "success" and TeamPlanBadge already uses it; the optional "Unknown" change for network errors is fine if you want to distinguish errors.

@vercel vercel bot temporarily deployed to Preview – nebula September 16, 2025 00:31 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 September 16, 2025 00:31 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground September 16, 2025 00:31 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui September 16, 2025 00:31 Inactive
@joaquim-verges joaquim-verges merged commit ea46572 into main Sep 16, 2025
23 of 24 checks passed
@joaquim-verges joaquim-verges deleted the cursor/display-eip7702-support-status-cd7c branch September 16, 2025 00:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Dashboard Involves changes to the Dashboard.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants