-
Notifications
You must be signed in to change notification settings - Fork 615
[BLD-389] Dashboard: Project Wallet section UI improvements and refactor #8291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
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. |
WalkthroughExtracts 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
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)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 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
🚀 New features to boost your workflow:
|
size-limit report 📦
|
There was a problem hiding this 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.
addressis 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 responsive100s 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 explicitlyAdd 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.
📒 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@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless 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@/typeswhere applicable
Prefertypealiases overinterfaceexcept for nominal shapes
Avoidanyandunknownunless 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.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsxapps/dashboard/src/@/components/blocks/wallet-address.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsxapps/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.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsxapps/dashboard/src/@/components/blocks/wallet-address.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsxapps/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
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/solana-wallets/components/create-solana-wallet.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsxapps/dashboard/src/@/components/blocks/wallet-address.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsxapps/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)
UseNavLinkfor internal navigation to get active state handling
Use Tailwind CSS for styling; no inline styles
Merge class names withcn()from@/lib/utilsfor conditional classes
Stick to design tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components must start withimport "server-only"; usenext/headers, server‑only env, heavy data fetching, andredirect()where appropriate
Client Components must start with'use client'; handle interactivity with hooks and browser APIs
Server-side data fetching: callgetAuthToken()from cookies, sendAuthorization: Bearer <token>header, and return typed results (avoidany)
Client-side data fetching: wrap calls in React Query with descriptive, stablequeryKeysand set sensiblestaleTime/cacheTime(≥ 60s default); keep tokens secret via internal routes or server actions
Do not importposthog-jsin 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.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsxapps/dashboard/src/@/components/blocks/wallet-address.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsx
apps/{dashboard,playground}/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Expose a
classNameprop 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.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsxapps/dashboard/src/@/components/blocks/wallet-address.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsxapps/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.tsxapps/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.tsxapps/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.tsxapps/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.tsxapps/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.tsxapps/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.tsxapps/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.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsxapps/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.tsxapps/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
disableDeprecatedanddisableChainIdpropsThe review comment is valid from a defensive coding perspective because:
- While current API is EVM-only, no explicit safeguard exists
- If any non-EVM chain enters the list, the modal will fail at runtime (toWei/EVM address operations)
- 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
SingleNetworkSelectorvia thechainIdsprop, 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 LGTMRendering 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 goodSwitch 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 addsrel="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 includerel="noopener noreferrer"for security reasons whentarget="_blank"is used. The script output confirms there are multiple usages ofUnderlineLinkthroughout the codebase, and some manually specifyrel="noopener noreferrer"while others (like the one under review) do not.The specific code at lines 288-294 in
project-wallet.tsxhas an external URL (https://portal.thirdweb.com/reference) withtarget="_blank"but norelattribute. 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 includerel="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 withtarget="_blank"The external link to
https://portal.thirdweb.com/referenceat lines 288–294 is missing therelattribute for security hardening. When usingtarget="_blank", you should always includerel="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.
...am/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
Show resolved
Hide resolved
...am/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
Show resolved
Hide resolved
...(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx
Show resolved
Hide resolved
...(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx
Show resolved
Hide resolved
...(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.tsx
Show resolved
Hide resolved
...oject_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsx
Show resolved
Hide resolved
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 -->
fcd7ebc to
6a7b556
Compare
There was a problem hiding this 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
errorhas amessageproperty. 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.
📒 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@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes
Avoidanyandunknownunless 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@/typeswhere applicable
Prefertypealiases overinterfaceexcept for nominal shapes
Avoidanyandunknownunless 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.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsxapps/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.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsxapps/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
UseNavLinkfor internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()from@/lib/utilsfor conditional class logic
Use design system tokens (e.g.,bg-card,border-border,text-muted-foreground)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader – never embed tokens in URLs
Return typed results (e.g.,Project[],User[]) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysfor React Query cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsxapps/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)
UseNavLinkfor internal navigation to get active state handling
Use Tailwind CSS for styling; no inline styles
Merge class names withcn()from@/lib/utilsfor conditional classes
Stick to design tokens (e.g., bg-card, border-border, text-muted-foreground)
Server Components must start withimport "server-only"; usenext/headers, server‑only env, heavy data fetching, andredirect()where appropriate
Client Components must start with'use client'; handle interactivity with hooks and browser APIs
Server-side data fetching: callgetAuthToken()from cookies, sendAuthorization: Bearer <token>header, and return typed results (avoidany)
Client-side data fetching: wrap calls in React Query with descriptive, stablequeryKeysand set sensiblestaleTime/cacheTime(≥ 60s default); keep tokens secret via internal routes or server actions
Do not importposthog-jsin server components (client-side only)
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/components/server-wallets-table.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsxapps/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
classNameprop 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.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/server-wallets/components/create-server-wallet.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/page.tsxapps/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.tsxapps/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.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsxapps/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
managementAccessTokenas 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
managementAccessTokenfromproject.servicesis 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
cnfor conditional styling is appropriate. The newbuttonprop 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
CreateServerWalletcomponent.
69-98: LGTM! Props interface correctly updated.The removal of
managementAccessTokenfromServerWalletsTablePropsis appropriate, as the wallet creation components now derive the token internally from theprojectprop.
135-135: LGTM! Component usage correctly updated.The
CreateServerWalletcall correctly provides onlyprojectandteamSlugprops, consistent with the component's updated interface wheremanagementAccessTokenis 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}/paymentsNo navigation issues detected.
| 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 } | ||
| : {}), | ||
| }); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.

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
ProjectWalletSetup.client.tsxandProjectWalletControls.client.tsx.ProjectFTUXto removemanagementAccessTokenprop.CreateSolanaWalletto use derivedmanagementAccessToken.wallet-address.tsx.ServerWalletsTableby removing unnecessary props.CreateServerWalletto include optional button props.ProjectWalletSectionto handle wallet creation and selection more effectively.ProjectWalletSection.Summary by CodeRabbit