Skip to content

Conversation

@MananTank
Copy link
Member

@MananTank MananTank commented Oct 22, 2025


PR-Codex overview

This PR focuses on refactoring and improving the wallet management components in the dashboard application, specifically enhancing the handling of project wallets and related functionalities.

Detailed summary

  • Deleted ProjectWalletSetup.client.tsx and ProjectWalletControls.client.tsx.
  • Updated ProjectFTUX to remove managementAccessToken prop.
  • Refactored CreateSolanaWallet to use derived managementAccessToken.
  • Simplified address handling in wallet-address.tsx.
  • Enhanced ServerWalletsTable by removing unnecessary props.
  • Modified CreateServerWallet to include optional button props.
  • Improved ProjectWalletSection to handle wallet creation and selection more effectively.
  • Added new storybook entries for ProjectWalletSection.
  • Introduced new UI components for wallet management, including dialogs and forms for sending funds.

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

Summary by CodeRabbit

  • New Features
    • Added a full project wallet management UI: view balance, send/receive funds, view transactions, change or create the project wallet.
  • Refactor
    • Moved wallet functionality into a dedicated top-level wallet section and simplified the first-time experience.
    • Streamlined authentication/config handling across dashboard wallet flows for a cleaner UI integration.

@vercel vercel bot temporarily deployed to Preview – thirdweb_playground October 22, 2025 15:26 Inactive
@linear
Copy link

linear bot commented Oct 22, 2025

@vercel
Copy link

vercel bot commented Oct 22, 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 Oct 22, 2025 4:40pm
4 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
docs-v2 Skipped Skipped Oct 22, 2025 4:40pm
nebula Skipped Skipped Oct 22, 2025 4:40pm
thirdweb_playground Skipped Skipped Oct 22, 2025 4:40pm
wallet-ui Skipped Skipped Oct 22, 2025 4:40pm

@vercel vercel bot temporarily deployed to Preview – nebula October 22, 2025 15:26 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui October 22, 2025 15:26 Inactive
@changeset-bot
Copy link

changeset-bot bot commented Oct 22, 2025

⚠️ No Changeset found

Latest commit: 6a7b556

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 vercel bot temporarily deployed to Preview – docs-v2 October 22, 2025 15:27 Inactive
@MananTank MananTank marked this pull request as ready for review October 22, 2025 15:27
@MananTank MananTank requested review from a team as code owners October 22, 2025 15:27
Copy link
Member Author

MananTank commented Oct 22, 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.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions github-actions bot added the Dashboard Involves changes to the Dashboard. label Oct 22, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 22, 2025

Walkthrough

Extracts and reorganizes project wallet UI: removes legacy wallet control/setup components, adds a new project-wallet module with details and creation flows, derives managementAccessToken from project.services, updates Storybook metadata, and adjusts sidebar/page rendering and props accordingly.

Changes

Cohort / File(s) Change Summary
Wallet control removals
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectWalletControls.client.tsx, apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectWalletSetup.client.tsx
Deleted client-side wallet controls and setup components, including send modal, form schemas, mutations, and related exports.
ProjectFTUX refactor & stories
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx, .../ProjectFTUX.stories.tsx
Removed wallet-related async fetching/props and WalletSection usage; simplified component signature to accept { project, teamSlug }. Updated Storybook meta and removed managementAccessToken from story args; adjusted decorator layout.
New project-wallet module
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx, .../project-wallet-details.tsx, .../project-wallet.stories.tsx
Added ProjectWalletSection / ProjectWalletSectionUI and ProjectWalletDetailsSection with wallet listing, balance display, send/receive/change-wallet modals, mutations, and storybook stories covering multiple scenarios. Exposes new named components.
Page & layout updates
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
Moved ProjectWalletSection to top-level of page render, removed managementAccessToken computation and wallet props from ProjectFTUX usage; adapted new ProjectWalletSection props (projectWallet, client).
Create server/solana wallet changes
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx, .../solana-wallets/components/create-solana-wallet.client.tsx
Converted CreateServerWallet to named export, removed managementAccessToken from prop list and derive it from project.services; added optional button prop (size/iconClassName). Updated CreateSolanaWallet signature to derive token similarly.
Server wallets table & transactions
.../transactions/components/server-wallets-table.client.tsx, .../transactions/page.tsx, .../wallets/page.tsx, .../transactions/analytics/ftux.client.tsx
Removed managementAccessToken from props and call sites; updated imports for CreateServerWallet (default→named) and removed internal helper CreateServerWalletStep; simplified rendering to use derived token.
Small utility change
apps/dashboard/src/@/components/blocks/wallet-address.tsx
Removed useMemo; compute address and shortenedAddress directly as constants instead of memoized values.

Sequence Diagram(s)

sequenceDiagram
    participant Page as Sidebar Page
    participant FTUX as ProjectFTUX
    participant WalletSection as ProjectWalletSection
    participant WalletDetails as ProjectWalletDetailsSection
    note over Page,WalletSection: New flow - wallet handled by dedicated module
    Page->>FTUX: render(project, teamSlug)
    Page->>WalletSection: render(project, teamSlug, projectWallet?, client)
    WalletSection->>WalletSection: call getProjectServerWallets (if token)
    WalletSection->>WalletDetails: render details or create UI
    WalletDetails->>WalletDetails: derive managementAccessToken from project.services
    WalletDetails->>WalletDetails: fetch balance, open send/receive/change dialogs
    WalletDetails->>API: sendProjectWalletTokens / updateDefaultProjectWallet (mutations)
    API-->>WalletDetails: success / error
    WalletDetails->>Page: invalidate queries / refresh routing (on success)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Project Wallet (Default Server Wallet) #8212: Modifies the same project wallet UI surface (ProjectFTUX, ProjectWalletSection, CreateServerWallet signatures and wallet-related mutations), indicating a closely related refactor of wallet management components.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.14% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description Check ⚠️ Warning The pull request description does not adequately follow the required template structure. While the description includes an auto-generated PR-Codex overview that provides useful summary information about the changes, the critical required sections from the template are missing or incomplete. Specifically, the title should follow the format "[SDK/Dashboard/Portal] Feature/Fix: Concise title," the Linear issue tag (BLD-389) is not explicitly provided in the PR description, the "Notes for the reviewer" section is absent, and the "How to test" section contains only the template placeholder without concrete testing instructions. The author left the template structure largely unfilled, relying instead on the automated PR-Codex summary to communicate the changes. The author should complete the pull request description by: (1) adding a properly formatted title following the "[SDK/Dashboard/Portal] Feature/Fix: Description" pattern, (2) explicitly including the Linear issue tag (BLD-389), (3) filling in the "Notes for the reviewer" section with any important context or considerations for reviewers, and (4) providing concrete testing instructions in the "How to test" section such as specific steps to verify the wallet UI changes, any affected user flows to test, or unit test commands to run. This will ensure the description provides complete guidance for reviewers and maintainers.
✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "[BLD-389] Dashboard: Project Wallet section UI improvements and refactor" clearly and concisely describes the primary changes in the changeset. It accurately reflects the main objectives: refactoring wallet-related components and improving the wallet UI. The title follows the repository's template format with the issue identifier (BLD-389), component scope (Dashboard), and specific description. The title is specific enough that a reviewer scanning the history would understand this PR focuses on wallet component improvements and refactoring efforts.
Linked Issues Check ✅ Passed The linked issue BLD-389 requests polishing the main project wallet card for both normal and empty states. The PR directly addresses this objective through multiple changes: it removes old wallet components (ProjectWalletSetup.client.tsx, ProjectWalletControls.client.tsx), creates new wallet management components (project-wallet.tsx, project-wallet-details.tsx), and refactors the wallet display with improved UI handling, dialogs, and forms for wallet operations. The new ProjectWalletSection components specifically manage wallet creation and selection, effectively polishing the wallet card presentation for different states, which aligns with the issue's stated goal.
Out of Scope Changes Check ✅ Passed All changes in the PR are directly scoped to wallet management and UI improvements within the dashboard. The modifications include refactoring wallet components (removing ProjectWalletSetup and ProjectWalletControls, creating new project-wallet components), simplifying wallet-related props across multiple files (removing managementAccessToken), optimizing wallet address handling (wallet-address.tsx), and enhancing wallet UI with new dialogs and forms (project-wallet-details.tsx). Each change contributes to the overall objective of improving wallet functionality and UI, with no unrelated features or bug fixes introduced.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bld-389

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • TEAM-0000: Entity not found: Issue - Could not find referenced Issue.

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

@codecov
Copy link

codecov bot commented Oct 22, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 54.90%. Comparing base (e0ace73) to head (6a7b556).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8291   +/-   ##
=======================================
  Coverage   54.90%   54.90%           
=======================================
  Files         919      919           
  Lines       60665    60665           
  Branches     4129     4129           
=======================================
  Hits        33310    33310           
  Misses      27254    27254           
  Partials      101      101           
Flag Coverage Δ
packages 54.90% <ø> (ø)
🚀 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 Oct 22, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 64.55 KB (0%) 1.3 s (0%) 312 ms (+95.78% 🔺) 1.7 s
thirdweb (cjs) 365.82 KB (0%) 7.4 s (0%) 1.7 s (+8.65% 🔺) 9 s
thirdweb (minimal + tree-shaking) 5.73 KB (0%) 115 ms (0%) 126 ms (+1234.33% 🔺) 241 ms
thirdweb/chains (tree-shaking) 526 B (0%) 11 ms (0%) 67 ms (+652.03% 🔺) 78 ms
thirdweb/react (minimal + tree-shaking) 19.09 KB (0%) 382 ms (0%) 86 ms (+767.48% 🔺) 468 ms

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: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx (1)

74-89: Make the curl example reliably runnable (don’t inject masked secrets; avoid ENS on testnets)

  • Masked secrets won’t work when pasted; always show a placeholder.
  • ENS (vitalik.eth) may not resolve on testnets; use a literal address that’s valid on the chosen chain.

Apply:

-  --header 'x-secret-key: ${project.secretKeys[0]?.masked ?? "<YOUR_SECRET_KEY>"}' \\
+  --header 'x-secret-key: <YOUR_SECRET_KEY>' \\
@@
-  "chainId": 421614,
+  "chainId": 11155111,
@@
-      "to": "vitalik.eth",
+      "to": "0x0000000000000000000000000000000000000001",

Optionally add a note below the code block: “Replace <YOUR_SECRET_KEY> and address/chainId as needed.” Based on coding guidelines.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx (1)

227-247: “Refresh Balance” doesn’t refetch EVM balances (query key mismatch)

You invalidate ["walletBalance", …], but EVM balances are fetched via thirdweb’s useWalletBalance, which uses its own internal query key. The button likely does nothing for EVM.

Two viable fixes:

  • Option A (preferred): Control the key and refetch.
    • Replace useWalletBalance with a local useQuery that calls a balance getter (e.g., thirdweb action) and uses an explicit key: ["walletBalance", address, chainId]. Your header button can then invalidate that exact key.
  • Option B: Pass a refresh nonce down and call refetch().
    • Add refreshNonce in ServerWalletsTable; increment it on click; pass to EVMWalletRow → WalletBalance; inside WalletBalance, useEffect(() => balance.refetch(), [refreshNonce]).

Sketch:

// In ServerWalletsTable
- await queryClient.invalidateQueries({ queryKey: ["walletBalance", selectedChainId] });
+ setRefreshNonce((n) => n + 1);

// state
+ const [refreshNonce, setRefreshNonce] = useState(0);

// pass down
- <EVMWalletRow ... />
+ <EVMWalletRow ... refreshNonce={refreshNonce} />

// In EVMWalletRow props and pass to WalletBalance
+ refreshNonce: number

// In WalletBalance
- const balance = useWalletBalance({...});
+ const balance = useWalletBalance({...});
+ useEffect(() => {
+   balance.refetch();
+ }, [refreshNonce]);

This guarantees the button triggers a refetch regardless of thirdweb’s internal keying.

Also applies to: 711-740

🧹 Nitpick comments (11)
apps/dashboard/src/@/components/blocks/wallet-address.tsx (3)

61-71: Propagate className to root in the “Invalid Address” branch.

Apply consumer styling on the outer element too.

-        <span className="flex items-center gap-2 underline-offset-4 hover:underline w-fit">
+        <span className={cn("flex items-center gap-2 underline-offset-4 hover:underline w-fit", props.className)}>

As per coding guidelines.


74-88: Propagate className to root in the ZERO_ADDRESS branch.

Expose root className consistently.

-    return (
-      <div className="flex items-center gap-2 py-2">
+    return (
+      <div className={cn("flex items-center gap-2 py-2", props.className)}>

As per coding guidelines.


90-185: Expose root className in the normal branch + remove redundant check.

  • Add a wrapper to accept className on the component root.
  • address is always defined; drop the conditional.
-  return (
-    <HoverCard>
+  return (
+    <div className={cn(props.className)}>
+    <HoverCard>
...
-          {address && (
-            <WalletAvatar
+          <WalletAvatar
               address={address}
               iconClassName={props.iconClassName}
               profiles={props.profiles.data}
               thirdwebClient={props.client}
               fallbackIcon={props.fallbackIcon}
-            />
-          )}
+            />
...
-    </HoverCard>
+    </HoverCard>
+    </div>
   );

As per coding guidelines.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx (1)

71-80: Match server-wallet UX: route to Vault when no token instead of opening modal.

Prevents a dead-end dialog and aligns flows.

-      <DialogTrigger asChild>
-        <Button
-          variant="default"
-          className="gap-2 rounded-full bg-foreground hover:bg-foreground/90"
-          disabled={props.disabled}
-        >
-          <PlusIcon className="size-4" />
-          Create Solana Wallet
-        </Button>
-      </DialogTrigger>
+      <Button
+        variant="default"
+        className="gap-2 rounded-full bg-foreground hover:bg-foreground/90"
+        disabled={props.disabled}
+        onClick={() => {
+          if (!managementAccessToken) {
+            router.push(`/team/${props.teamSlug}/${props.project.slug}/vault`);
+          } else {
+            setOpen(true);
+          }
+        }}
+      >
+        <PlusIcon className="size-4" />
+        Create Solana Wallet
+      </Button>

As per coding guidelines.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx (1)

72-80: Expose className on the root element of ProjectWalletDetailsSection.

Required by dashboard component guidelines.

 type ProjectWalletControlsProps = {
   projectWallet: ProjectWalletSummary;
   project: Project;
   defaultChainId?: number;
   teamSlug: string;
   getProjectServerWallets: GetProjectServerWallets;
   client: ThirdwebClient;
+  className?: string;
 };
@@
-  return (
-    <div>
+  return (
+    <div className={cn(props.className)}>

As per coding guidelines.

Also applies to: 128-133

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx (1)

5-20: Add stories for the new Project Wallet components.

Please include stories for ProjectWalletDetailsSection (and related dialogs) under project-wallet to aid review and visual regression.

Based on learnings.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx (1)

21-33: Expose className and mark this file server-only

  • Add import "server-only" at top to prevent accidental client bundling.
  • Expose an optional className on the exported component and merge with cn() on the root element. As per coding guidelines.

Apply:

+import "server-only";
+import { cn } from "@/lib/utils";
...
-export function ProjectFTUX(props: { project: Project; teamSlug: string }) {
+export function ProjectFTUX(props: { project: Project; teamSlug: string; className?: string }) {
   return (
-    <div className="flex flex-col gap-10">
+    <div className={cn("flex flex-col gap-10", props.className)}>

Based on coding guidelines.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx (1)

89-100: Reduce artificial loading delay to keep Storybook responsive

100s delay is excessive for manual testing; 2–5s is enough to demonstrate the loading state.

-      await new Promise((resolve) => setTimeout(resolve, 100000));
+      await new Promise((resolve) => setTimeout(resolve, 3000));

Based on learnings.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (1)

1-1: Mark this server file explicitly

Add import "server-only" at the top to enforce server execution for this page.

+import "server-only";
 import { EmptyStateCard } from "app/(app)/team/components/Analytics/EmptyStateCard";

As per coding guidelines.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx (2)

146-153: Render a clear error state for serverWalletsQuery (with retry).

Only loading/empty states are handled; errors silently fall back. Show a message and an inline Retry.

Apply:

-        {serverWalletsQuery.isLoading ? (
+        {serverWalletsQuery.isLoading ? (
           <Skeleton className="h-[36px] max-w-lg rounded-full" />
-        ) : canSelectExisting ? (
+        ) : serverWalletsQuery.isError ? (
+          <div className="text-sm text-destructive">
+            Failed to load server wallets.
+            <Button
+              className="ml-2"
+              size="sm"
+              variant="outline"
+              onClick={() => serverWalletsQuery.refetch()}
+            >
+              Retry
+            </Button>
+          </div>
+        ) : canSelectExisting ? (
           <div className="flex items-center gap-3">

As per coding guidelines.

Also applies to: 188-225


36-39: Type placement: consider moving GetProjectServerWallets to a local types barrel.

If reused across files, promote this type into a colocated types.ts for consistency and re‑use.

As per coding guidelines.

📜 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 e0ace73 and fcd7ebc.

📒 Files selected for processing (15)
  • apps/dashboard/src/@/components/blocks/wallet-address.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectWalletControls.client.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectWalletSetup.client.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx (0 hunks)
💤 Files with no reviewable changes (4)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectWalletControls.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectWalletSetup.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{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)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/@/components/blocks/wallet-address.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.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)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/@/components/blocks/wallet-address.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.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)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/@/components/blocks/wallet-address.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.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)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/@/components/blocks/wallet-address.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.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)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/@/components/blocks/wallet-address.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
**/*.stories.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

For new UI components, add Storybook stories (*.stories.tsx) alongside the code

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx
apps/{dashboard,playground}/**/*.stories.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Add Storybook stories (*.stories.tsx) alongside new UI components

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx
🧠 Learnings (6)
📚 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}/**/*.stories.tsx : Add Storybook stories (`*.stories.tsx`) alongside new UI components

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.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/**/components/*.{stories,test}.{tsx,ts} : Provide a Storybook story (`MyComponent.stories.tsx`) or unit test alongside the component.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.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 **/*.stories.tsx : For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.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 : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout changes.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout PR #7888.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
🧬 Code graph analysis (7)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/lib/vault.client.ts (1)
  • createSolanaAccount (131-200)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx (1)
  • ProjectWalletSectionUI (273-314)
apps/dashboard/src/@/storybook/stubs.ts (1)
  • projectStub (6-25)
apps/dashboard/src/@/lib/server/project-wallet.ts (1)
  • ProjectWalletSummary (8-12)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx (1)
  • CreateServerWallet (21-154)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx (8)
apps/dashboard/src/@/lib/server/project-wallet.ts (1)
  • ProjectWalletSummary (8-12)
apps/dashboard/src/@/hooks/chains/v5-adapter.ts (1)
  • useV5DashboardChain (14-28)
apps/dashboard/src/@/components/ui/CopyTextButton.tsx (1)
  • CopyTextButton (9-68)
apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx (1)
  • SingleNetworkSelector (152-298)
apps/dashboard/src/@/components/blocks/fund-wallets-modal/index.tsx (1)
  • FundWalletModal (76-93)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts (1)
  • updateDefaultProjectWallet (190-216)
apps/dashboard/src/@/components/blocks/wallet-address.tsx (1)
  • WalletAddress (29-44)
apps/dashboard/src/@/actions/project-wallet/send-tokens.ts (1)
  • sendProjectWalletTokens (12-74)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx (6)
apps/dashboard/src/@/lib/server/project-wallet.ts (1)
  • ProjectWalletSummary (8-12)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts (1)
  • updateDefaultProjectWallet (190-216)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx (1)
  • CreateServerWallet (21-154)
apps/dashboard/src/@/components/blocks/wallet-address.tsx (1)
  • WalletAddress (29-44)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx (1)
  • ProjectWalletDetailsSection (81-288)
apps/dashboard/src/@/actions/project-wallet/list-server-wallets.ts (1)
  • listProjectServerWallets (18-70)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx (1)
  • CreateServerWallet (21-154)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx (1)
  • ProjectWalletSection (316-331)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx (1)
  • ProjectFTUX (21-33)
⏰ 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: Lint Packages
  • GitHub Check: Size
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (7)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx (1)

31-37: LGTM — CreateServerWallet integration is clean and consistent.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx (2)

506-521: No issues found; sendProjectWalletTokens is correctly implemented as a server action.

The file begins with "use server", confirming it runs exclusively server-side and never leaks secrets to the browser. Importing and calling server actions from client components is safe and the intended pattern in Next.js. The code aligns with coding guidelines for keeping tokens secret.


232-243: Let me verify what chains the API returns and if there's any EVM type discrimination:<!-- [scratchpad_update]
[task verify_evm_filtering 3/3]
Web search results show:

  • thirdweb supports EVM-compatible chains (700+)
  • Solana support was DISCONTINUED as of October 9, 2023
  • Current chainlist appears to be EVM-only now
  • Historical support for Solana existed but was ended

[critical_finding]
The review comment may be based on older information. Based on the blog post (item 7), thirdweb discontinued Solana support in October 2023. Current chainlist API likely returns only EVM chains.

However, the code structure shows NO explicit EVM filtering in SingleNetworkSelector. If the API were to include non-EVM chains in the future, or if there's any non-EVM chain in the list, the selector would display them without filtering.

[decision]
The CONCERN in the review comment is valid from a defensive coding perspective:

  • No EVM filter exists in the component
  • If API returns non-EVM chains, modal will fail (toWei, EVM address won't work)
  • Coding best practice: explicit EVM filtering should be applied to be safe

The issue is not critical TODAY (if API only returns EVM), but it's a latent bug risk.

Based on my verification, thirdweb's tools work with any contract deployed on any EVM-compatible chain or Solana, though thirdweb ended support for Solana on October 9th, 2023. The chainlist API currently appears EVM-only.

However, examining the code reveals a critical finding:

In SingleNetworkSelector (apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx):

  • No explicit EVM-only filtering exists
  • All chains from useAllChainsData() are displayed (except deprecated/testnet filters)
  • The modal context (project-wallet-details.tsx lines 232-243) uses only disableDeprecated and disableChainId props

The review comment is valid from a defensive coding perspective because:

  1. While current API is EVM-only, no explicit safeguard exists
  2. If any non-EVM chain enters the list, the modal will fail at runtime (toWei/EVM address operations)
  3. Best practice: explicitly filter to EVM chains

Ensure the network selector lists only EVM chains for this flow.

This modal sends native EVM tokens (toWei, EVM address); non-EVM choices will fail. Pass an explicit EVM-only filter to SingleNetworkSelector via the chainIds prop, or add EVM-type discrimination to the component. If the complete list of EVM chain IDs is available in the codebase, reference it; otherwise, document why the current implicit filtering is sufficient.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (1)

133-138: Wallet section placement LGTM

Rendering ProjectWalletSection unconditionally before the analytics/FTUX branch clarifies the overview and matches the refactor intent.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx (1)

61-61: Import/use of CreateServerWallet looks good

Switch to named import and prop surface aligns with the refactor.

Also applies to: 135-146

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx (2)

41-53: Small UX nit: initial selection logic is good — keep it.

effectiveSelectedWalletId and selectedWallet memoization correctly guard missing/removed IDs and choose the first wallet as a sensible default. No changes needed.

Please ensure serverWallets are already sorted in desired priority; otherwise, consider sorting by label/createdAt before picking index 0.

Also applies to: 75-97


288-294: I need to see the full implementation of the UnderlineLink component to determine if it automatically adds rel="noopener noreferrer":<!-- [scratchpad_update]
[observations]
Web search confirms: Next.js Link component does NOT automatically add rel="noopener noreferrer" when target="_blank" is used. Must be manually specified. The security best practice is to always include rel="noopener noreferrer" when using target="_blank" on external links to prevent reverse tabnabbing attacks.

[analysis]

  • UnderlineLink wraps Next.js Link component
  • Next.js Link does NOT auto-add rel
  • The specific code at project-wallet.tsx:288-294 is EXTERNAL URL with target="_blank" but NO rel attribute
  • This is a legitimate security concern
  • Review comment is valid
  • Need to view full UnderlineLink implementation to understand if it should auto-add rel when target="_blank"
    [scratchpad_end] -->Now let me check the actual UnderlineLink implementation directly from the codebase:Based on my analysis, Next.js Link component does not automatically include rel="noopener noreferrer" for security reasons when target="_blank" is used. The script output confirms there are multiple usages of UnderlineLink throughout the codebase, and some manually specify rel="noopener noreferrer" while others (like the one under review) do not.

The specific code at lines 288-294 in project-wallet.tsx has an external URL (https://portal.thirdweb.com/reference) with target="_blank" but no rel attribute. Per the learnings, rel="noopener noreferrer" is only unnecessary for internal links (starting with /), but this is an external URL.

When using target="_blank", you should always include rel="noopener noreferrer" for security reasons to prevent the new page from accessing the window.opener property and to protect your site from potential malicious scripts.

The review comment is valid: the external link in the code snippet lacks the required security attribute.


Add rel="noopener noreferrer" to external link with target="_blank"

The external link to https://portal.thirdweb.com/reference at lines 288–294 is missing the rel attribute for security hardening. When using target="_blank", you should always include rel="noopener noreferrer" for security reasons.

<UnderlineLink
  href="https://portal.thirdweb.com/reference"
  target="_blank"
  rel="noopener noreferrer"
>
  thirdweb API
</UnderlineLink>
⛔ Skipped due to learnings
Learnt from: MananTank
PR: thirdweb-dev/js#7812
File: apps/dashboard/src/app/(app)/(dashboard)/published-contract/components/token-banner.tsx:48-60
Timestamp: 2025-08-07T20:43:21.864Z
Learning: In the TokenBanner component at apps/dashboard/src/app/(app)/(dashboard)/published-contract/components/token-banner.tsx, the Link components use target="_blank" with internal application routes (starting with "/") to open pages in new tabs within the same application. These internal links do not require rel="noopener noreferrer" security attributes, which are only needed for external URLs.
Learnt from: MananTank
PR: thirdweb-dev/js#7984
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/components/FeatureCard.client.tsx:93-99
Timestamp: 2025-09-05T19:45:22.949Z
Learning: In the thirdweb dashboard project, rel="noopener noreferrer" attributes are not required for external links with target="_blank" in Link components, as confirmed by MananTank.

@graphite-app
Copy link
Contributor

graphite-app bot commented Oct 22, 2025

Merge activity

…tor (#8291)

<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview

This PR primarily focuses on refactoring and improving the handling of project wallets within the application. It removes unused components, simplifies props, and enhances the user interface for wallet management.

### Detailed summary

- Deleted unused files: `ProjectWalletSetup.client.tsx` and `ProjectWalletControls.client.tsx`.
- Updated `ProjectFTUX` to remove `managementAccessToken` prop.
- Simplified `CreateSolanaWallet` and `CreateServerWallet` components by removing unnecessary props.
- Enhanced styling in the `ProjectFTUX` story and the wallet-related components.
- Improved state management for wallet selection and transactions.
- Refactored `ProjectWalletSection` to streamline wallet creation and management processes.

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

<!-- end pr-codex -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

* **New Features**
  * Added comprehensive project wallet management interface with send, receive, view transactions, and change wallet actions through an interactive dashboard.

* **Refactor**
  * Reorganized wallet functionality into a dedicated module for improved code organization.
  * Simplified component interfaces by removing redundant authentication parameters throughout the dashboard.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@vercel vercel bot temporarily deployed to Preview – nebula October 22, 2025 16:33 Inactive
@vercel vercel bot temporarily deployed to Preview – wallet-ui October 22, 2025 16:33 Inactive
@vercel vercel bot temporarily deployed to Preview – docs-v2 October 22, 2025 16:33 Inactive
@vercel vercel bot temporarily deployed to Preview – thirdweb_playground October 22, 2025 16:33 Inactive
@graphite-app graphite-app bot merged commit 6a7b556 into main Oct 22, 2025
23 of 24 checks passed
@graphite-app graphite-app bot deleted the bld-389 branch October 22, 2025 16:41
@vercel vercel bot temporarily deployed to Production – wallet-ui October 22, 2025 16:41 Inactive
@vercel vercel bot temporarily deployed to Production – nebula October 22, 2025 16:41 Inactive
@vercel vercel bot temporarily deployed to Production – thirdweb_playground October 22, 2025 16:41 Inactive
@vercel vercel bot temporarily deployed to Production – docs-v2 October 22, 2025 16:41 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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx (1)

22-26: Add explicit return type annotation.

The exported function lacks an explicit return type. Per coding guidelines, all functions should have explicit return types.

As per coding guidelines.

Apply this diff:

-export function CreateSolanaWallet(props: {
+export function CreateSolanaWallet(props: {
   project: Project;
   teamSlug: string;
   disabled?: boolean;
-}) {
+}): JSX.Element {
♻️ Duplicate comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx (1)

465-481: Amount validation should ensure numeric > 0.

This has already been flagged earlier in the PR; avoid duplicate.

🧹 Nitpick comments (10)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx (1)

31-33: Consider extracting the service name constant.

The service name "engineCloud" is hardcoded here. If this service name is used in multiple places or might change, consider extracting it to a shared constant for maintainability and discoverability.

Example:

const ENGINE_CLOUD_SERVICE_NAME = "engineCloud";

const managementAccessToken =
  props.project.services?.find((service) => service.name === ENGINE_CLOUD_SERVICE_NAME)
    ?.managementAccessToken ?? undefined;
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx (3)

21-29: Add explicit return type to the function.

The coding guidelines require explicit return types for TypeScript functions. As per coding guidelines.

Apply this diff:

-export function CreateServerWallet(props: {
+export function CreateServerWallet(props: {
   project: Project;
   teamSlug: string;
   setAsProjectWallet?: boolean;
   button?: {
     size?: "default" | "sm" | "lg";
     iconClassName?: string;
   };
-}) {
+}): JSX.Element {

58-60: Improve error handling for better type safety.

The error handler assumes error has a message property. Add a type guard to handle non-Error instances defensively.

Apply this diff:

     onError: (error) => {
-      toast.error(error.message);
+      toast.error(error instanceof Error ? error.message : "Failed to create server wallet");
     },

63-72: Consider using ES6 object property shorthand.

On Line 69, the property assignment can use ES6 shorthand since the key and value have the same name.

Apply this diff:

       await createEoaMutation.mutateAsync({
         label,
-        managementAccessToken: managementAccessToken,
+        managementAccessToken,
       });
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx (1)

21-21: Add explicit return type and optional className; consider marking server-only.

  • Give ProjectFTUX an explicit return type and accept a className applied to the root div.
  • Since this is a server component, prepend import "server-only"; at the top for clarity.
+import "server-only";
@@
-export function ProjectFTUX(props: { project: Project; teamSlug: string }) {
+export function ProjectFTUX(
+  props: { project: Project; teamSlug: string; className?: string },
+): JSX.Element {
   return (
-    <div className="flex flex-col gap-10">
+    <div className={cn("flex flex-col gap-10", props.className)}>
       …
     </div>
   );
 }

Note: cn is already part of the shared utils; import it if not present. As per coding guidelines.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx (3)

486-497: Unify client typing to ThirdwebClient.

ProjectWalletDetailsSection uses ThirdwebClient, but SendProjectWalletModalProps uses ReturnType. Prefer a single public type.

-type SendProjectWalletModalProps = {
+type SendProjectWalletModalProps = {
   open: boolean;
   onClose: () => void;
   onSuccess: () => void;
   walletAddress: string;
   publishableKey: string;
   teamId: string;
   chainId: number;
   label: string;
-  client: ReturnType<typeof getClientThirdwebClient>;
+  client: ThirdwebClient;
   isManagedVault: boolean;
 };

539-546: Default amount "0" conflicts with intended positive-amount validation.

Initialize amount to an empty string to avoid accidental zero submits and align with numeric>0 validation.

   const form = useForm<SendFormValues>({
     defaultValues: {
-      amount: "0",
+      amount: "",
       chainId,
       secretKey: "",
       vaultAccessToken: "",
       toAddress: "",
     },

649-667: Improve UX: numeric input and pattern.

Use type="text" with inputMode="decimal" (kept) but add a numeric-only pattern to assist mobile keyboards, or switch to a controlled number field component if available.

-<Input inputMode="decimal" min="0" step="any" {...field} />
+<Input inputMode="decimal" inputMode="decimal" pattern="[0-9]*[.]?[0-9]*" {...field} />

Note: min/step don’t apply to text inputs; validation remains handled by zod.

Also applies to: 656-656

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx (1)

89-100: Consider shorter artificial delay for loading story.

100s may feel hung in Storybook; 2–5s usually illustrates loading without friction.

-      await new Promise((resolve) => setTimeout(resolve, 100000));
+      await new Promise((resolve) => setTimeout(resolve, 3000));
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (1)

72-72: Mark server file explicitly as server-only.

Add import "server-only"; at the top for clarity and to prevent accidental client usage.

+import "server-only";
📜 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 fcd7ebc and 6a7b556.

📒 Files selected for processing (15)
  • apps/dashboard/src/@/components/blocks/wallet-address.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectWalletControls.client.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectWalletSetup.client.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx (0 hunks)
💤 Files with no reviewable changes (4)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectWalletSetup.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectWalletControls.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/page.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsx
  • apps/dashboard/src/@/components/blocks/wallet-address.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{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)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.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)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.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)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.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)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.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)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx
**/*.stories.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

For new UI components, add Storybook stories (*.stories.tsx) alongside the code

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
apps/{dashboard,playground}/**/*.stories.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Add Storybook stories (*.stories.tsx) alongside new UI components

Files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
🧠 Learnings (13)
📚 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)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.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}/**/*.stories.tsx : Add Storybook stories (`*.stories.tsx`) alongside new UI components

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.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/**/components/*.{stories,test}.{tsx,ts} : Provide a Storybook story (`MyComponent.stories.tsx`) or unit test alongside the component.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.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 **/*.stories.tsx : For new UI components, add Storybook stories (`*.stories.tsx`) alongside the code

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx
📚 Learning: 2025-10-22T15:45:54.684Z
Learnt from: MananTank
PR: thirdweb-dev/js#8291
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx:100-114
Timestamp: 2025-10-22T15:45:54.684Z
Learning: The `managementAccessToken` from `project.services.engineCloud.managementAccessToken` in the dashboard codebase is not a secret token and can be safely included in React Query keys and props without security concerns.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.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} : Keep tokens secret via internal API routes or server actions

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.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 : Prefer API routes or server actions to keep tokens secret; the browser only sees relative paths.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.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} : 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

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.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} : Use descriptive, stable `queryKeys` for React Query cache hits

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.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 : Keep `queryKey` stable and descriptive for cache hits.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
📚 Learning: 2025-06-26T19:46:04.024Z
Learnt from: gregfromstl
PR: thirdweb-dev/js#7450
File: packages/thirdweb/src/bridge/Webhook.ts:57-81
Timestamp: 2025-06-26T19:46:04.024Z
Learning: In the onramp webhook schema (`packages/thirdweb/src/bridge/Webhook.ts`), the `currencyAmount` field is intentionally typed as `z.number()` while other amount fields use `z.string()` because `currencyAmount` represents fiat currency amounts in decimals (like $10.50), whereas other amount fields represent token amounts in wei (very large integers that benefit from bigint representation). The different naming convention (`currencyAmount` vs `amount`) reflects this intentional distinction.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout changes.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout PR #7888.

Applied to files:

  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
🧬 Code graph analysis (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx (1)
  • CreateServerWallet (21-154)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx (1)
  • ProjectWalletSectionUI (273-314)
apps/dashboard/src/@/storybook/stubs.ts (1)
  • projectStub (6-25)
apps/dashboard/src/@/lib/server/project-wallet.ts (1)
  • ProjectWalletSummary (8-12)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx (9)
apps/dashboard/src/@/lib/server/project-wallet.ts (1)
  • ProjectWalletSummary (8-12)
apps/dashboard/src/@/hooks/chains/v5-adapter.ts (1)
  • useV5DashboardChain (14-28)
apps/dashboard/src/@/components/ui/CopyTextButton.tsx (1)
  • CopyTextButton (9-68)
apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx (1)
  • SingleNetworkSelector (152-298)
apps/dashboard/src/@/components/blocks/fund-wallets-modal/index.tsx (1)
  • FundWalletModal (76-93)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/lib/vault.client.ts (1)
  • updateDefaultProjectWallet (190-216)
apps/dashboard/src/@/components/blocks/wallet-address.tsx (1)
  • WalletAddress (29-44)
apps/dashboard/src/@/actions/project-wallet/send-tokens.ts (1)
  • sendProjectWalletTokens (12-74)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectWalletControls.client.tsx (1)
  • ProjectWalletControls (76-450)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx (1)
  • ProjectWalletSection (316-331)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx (1)
  • ProjectFTUX (21-33)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/lib/vault.client.ts (1)
  • createSolanaAccount (131-200)
⏰ 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). (5)
  • GitHub Check: Size
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: Build Packages
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (11)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsx (1)

31-42: Good refactor: token derivation internalized.

The refactor successfully moves token retrieval logic inside the component, eliminating the need to pass managementAccessToken as a prop. This encapsulation improves the component's API and aligns well with the broader PR refactor.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx (2)

34-37: LGTM! Token derivation is appropriate.

The derivation of managementAccessToken from project.services is secure and appropriate. Based on learnings.


76-109: LGTM! Button implementation is clean and correct.

The button rendering logic correctly handles all states (loading, with/without token), and the use of cn for conditional styling is appropriate. The new button prop provides good customization flexibility.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsx (3)

61-61: LGTM! Import correctly updated to named export.

The import change from default to named export is consistent with the refactored CreateServerWallet component.


69-98: LGTM! Props interface correctly updated.

The removal of managementAccessToken from ServerWalletsTableProps is appropriate, as the wallet creation components now derive the token internally from the project prop.


135-135: LGTM! Component usage correctly updated.

The CreateServerWallet call correctly provides only project and teamSlug props, consistent with the component's updated interface where managementAccessToken is derived internally.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx (2)

100-114: Good: stable React Query config and cache key.

Enabled flag + 60s staleTime are sensible; including managementAccessToken in the queryKey is fine here for cache separation. Based on learnings.


342-349: Good: invalidate with the same queryKey shape.

Query invalidation mirrors the fetch key (including managementAccessToken).

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsx (1)

1-26: Stories look good and exercise key states.

Meta, decorators, and scenarios are set up well.

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx (1)

133-139: Nice placement of ProjectWalletSection.

Rendering the wallet section above analytics and FTUX keeps it discoverable.

Also applies to: 156-156

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx (1)

93-128: All four product links reference valid routes. The page.tsx files exist for:

  • /team/{teamSlug}/{projectSlug}/transactions
  • /team/{teamSlug}/{projectSlug}/contracts
  • /team/{teamSlug}/{projectSlug}/insight
  • /team/{teamSlug}/{projectSlug}/payments

No navigation issues detected.

Comment on lines +553 to +570
mutationFn: async (values: SendFormValues) => {
const quantityWei = toWei(values.amount).toString();
const secretKeyValue = values.secretKey.trim();
const vaultAccessTokenValue = values.vaultAccessToken.trim();

const result = await sendProjectWalletTokens({
chainId: values.chainId,
publishableKey,
quantityWei,
recipientAddress: values.toAddress,
teamId,
walletAddress,
secretKey: secretKeyValue,
...(vaultAccessTokenValue
? { vaultAccessToken: vaultAccessTokenValue }
: {}),
});

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep secrets on the server: ensure sendProjectWalletTokens runs server-side.

sendProjectWalletTokens is invoked from a client component. Make the action server-only and call it via an internal route or a server action to avoid bundling request details and to align with “keep tokens secret” guidance.

-// apps/dashboard/src/@/actions/project-wallet/send-tokens.ts
+// apps/dashboard/src/@/actions/project-wallet/send-tokens.ts
+import "server-only";
 export async function sendProjectWalletTokens(…) { … }

If converting to a Next server action isn’t feasible here, expose a POST API route that calls sendProjectWalletTokens server-side and have the client call that endpoint. As per coding guidelines.

Committable suggestion skipped: line range outside the PR's diff.

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