-
Notifications
You must be signed in to change notification settings - Fork 619
[MNY-115] Dashboard: Fix token creation flow not working for custom chains #7896
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
[MNY-115] Dashboard: Fix token creation flow not working for custom chains #7896
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds a v5 dashboard chain adapter hook and refactors token/NFT creation flows to use it for chain resolution instead of runtime defineChain; updates imports, query keys, and TokenProvider/deploy paths to consume resolved Dashboard Chain objects. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant UI as Page / Component
participant HookFactory as useGetV5DashboardChain()
participant HookSingle as useV5DashboardChain
participant Map as idToChain
participant Def as defineDashboardChain
participant Ops as Deployment / TokenProvider / Queries
UI->>HookFactory: const getChain = useGetV5DashboardChain()
UI->>HookFactory: getChain(chainId)
HookFactory->>Map: lookup metadata (idToChain.get(chainId))
HookFactory->>Def: defineDashboardChain(chainId, metadata)
Def-->>HookFactory: Dashboard Chain
HookFactory-->>UI: Dashboard Chain
UI->>Ops: call deploy/provider/query with Dashboard Chain
alt existing single-hook usage
UI->>HookSingle: useV5DashboardChain(chainId)
HookSingle->>Map: lookup & defineDashboardChain(...)
HookSingle-->>UI: Dashboard Chain
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Assessment against linked issues
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
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. |
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7896 +/- ##
=======================================
Coverage 56.53% 56.53%
=======================================
Files 904 904
Lines 58592 58592
Branches 4143 4143
=======================================
Hits 33126 33126
Misses 25360 25360
Partials 106 106
🚀 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: 0
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)/tokens/create/token/create-token-page.client.tsx (2)
100-113: Use a stable, serializable query key and gate query until chain is readyUsing the Chain object in a React Query key can lead to cache misses due to object identity and serialization. Also, the query can fire with an undefined chain on first render. Use the numeric chainId in the key, set enabled, and add a conservative staleTime to reduce refetches.
Apply this diff:
- const isERC20AssetSupportedQuery = useQuery({ - queryKey: ["is-erc20-asset-supported", chain], + const isERC20AssetSupportedQuery = useQuery({ + queryKey: ["is-erc20-asset-supported", Number(tokenInfoForm.watch("chain"))], queryFn: async () => { try { const res = await getDeployedContractFactory({ // eslint-disable-next-line no-restricted-syntax - chain: chain, + chain: chain, client: props.client, }); return !!res; } catch { return false; } }, + enabled: !!chain, + staleTime: 60_000, });
115-127: Mirror the same improvements on router-enabled queryKey off the chainId (not the Chain object), and gate execution until chain is available. Add staleTime for sensible caching.
Apply this diff:
- const isAssetRouterEnabledQuery = useQuery({ + const isAssetRouterEnabledQuery = useQuery({ queryFn: async () => { try { return await isPoolRouterEnabled({ - chain: chain, + chain: chain, client: props.client, }); } catch { return false; } }, - queryKey: ["is-asset-router-enabled", chain], + queryKey: ["is-asset-router-enabled", Number(tokenInfoForm.watch("chain"))], + enabled: !!chain, + staleTime: 60_000, });
🧹 Nitpick comments (7)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsx (1)
63-63: Consider guarding against missing custom metadata before deploy/lookupIf idToChain isn't populated yet (slow network, first load), getChain(Number(...)) may fall back to a default chain definition without the custom RPC, risking the same RPC routing failure seen in MNY-115. Two light options:
- Block actions until chain metadata is ready.
- Validate the chain object (e.g., has expected RPC URL) and surface a friendly error/toast if not.
I can wire a tiny helper that checks readiness and disables the launch button until resolved.
Also applies to: 91-91
apps/dashboard/src/@/hooks/chains/v5-adapter.ts (2)
30-39: Add an explicit return type for stability and DXSmall typing nit: declare the return type so the hook’s API stays stable and discoverable.
Apply this diff:
-export function useGetV5DashboardChain() { +export function useGetV5DashboardChain(): (chainId: number) => Chain { const { idToChain } = useAllChainsData(); return useCallback( (chainId: number) => { // eslint-disable-next-line no-restricted-syntax return defineDashboardChain(chainId, idToChain.get(chainId)); }, [idToChain], ); }
19-27: Optional: Protect custom networks from silent fallbackIf idToChain lacks metadata for a custom chain, defineDashboardChain(chainId, undefined) may produce a generic chain that routes via default RPCs. Consider a dev-time invariant/log when idToChain.get(chainId) is undefined for a non-known chain to surface configuration issues early. I can add a DEV-only warn with a single line guard.
Also applies to: 30-39
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx (3)
114-119: Consistency nit: avoid passing “chain: chain” and parse onceNot functional, but a quick cleanup improves readability:
- Prefer “chain,” shorthand.
- Parse chainId to number once per function and reuse.
Apply this diff:
- const chain = getChain(Number(params.values.chain)); + const chainId = Number(params.values.chain); + const chain = getChain(chainId); @@ - chain: chain, + chain,And similarly in DropERC20_deployContract:
- const chain = getChain(Number(params.values.chain)); + const chainId = Number(params.values.chain); + const chain = getChain(chainId); @@ - chain: chain, + chain,Also applies to: 249-254
156-163: Analytics label mismatch (‘ERC20Asset’ path reported as ‘DropERC20’)This is likely skewing metrics. In the ERC20Asset_deployContract flow, contractType is “ERC20Asset” when saving to the project, but reportContractDeployed uses contractName: "DropERC20".
Apply this diff:
- reportContractDeployed({ - address: contractAddress, - chainId: Number(params.values.chain), - contractName: "DropERC20", - deploymentType: "asset", - publisher: account.address, - }); + reportContractDeployed({ + address: contractAddress, + chainId: Number(params.values.chain), + contractName: "ERC20Asset", + deploymentType: "asset", + publisher: account.address, + });
454-456: Likely wrong path segment (projectId vs projectSlug) for revalidationRoutes are under [project_slug], but the revalidate path uses props.projectId. This can prevent cache invalidation for the visible page.
Apply this diff:
- revalidatePathAction( - `/team/${props.teamSlug}/project/${props.projectId}/tokens`, - "page", - ); + revalidatePathAction( + `/team/${props.teamSlug}/project/${props.projectSlug}/tokens`, + "page", + );apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx (1)
506-507: TokenProvider chain: safe usage, but consider a tiny guard for edge casesIn practice chainId is always provided, but a defensive check (e.g., render Skeleton until chain exists) would avoid passing undefined in any edge case. Low priority.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
apps/dashboard/src/@/hooks/chains/v5-adapter.ts(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsx(4 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx(4 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx(5 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page.client.tsx(3 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{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
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsxapps/dashboard/src/@/hooks/chains/v5-adapter.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.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)/tokens/create/token/create-token-page.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsxapps/dashboard/src/@/hooks/chains/v5-adapter.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.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)/tokens/create/token/create-token-page.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsxapps/dashboard/src/@/hooks/chains/v5-adapter.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx
🧠 Learnings (7)
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsxapps/dashboard/src/@/hooks/chains/v5-adapter.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx
📚 Learning: 2025-06-17T18:30:52.976Z
Learnt from: MananTank
PR: thirdweb-dev/js#7356
File: apps/nebula/src/app/not-found.tsx:1-1
Timestamp: 2025-06-17T18:30:52.976Z
Learning: In the thirdweb/js project, the React namespace is available for type annotations (like React.FC) without needing to explicitly import React. This is project-specific configuration that differs from typical TypeScript/React setups.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page.client.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsxapps/dashboard/src/@/hooks/chains/v5-adapter.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx
📚 Learning: 2025-07-07T21:21:47.488Z
Learnt from: saminacodes
PR: thirdweb-dev/js#7543
File: apps/portal/src/app/pay/page.mdx:4-4
Timestamp: 2025-07-07T21:21:47.488Z
Learning: In the thirdweb-dev/js repository, lucide-react icons must be imported with the "Icon" suffix (e.g., ExternalLinkIcon, RocketIcon) as required by the new linting rule, contrary to the typical lucide-react convention of importing without the suffix.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx
📚 Learning: 2025-05-30T17:14:25.332Z
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : For notices & skeletons rely on `AnnouncementBanner`, `GenericLoadingPage`, `EmptyStateCard`.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*.{tsx,jsx} : Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx
🧬 Code graph analysis (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page.client.tsx (1)
apps/dashboard/src/@/hooks/chains/v5-adapter.ts (1)
useV5DashboardChain(14-28)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx (1)
apps/dashboard/src/@/hooks/chains/v5-adapter.ts (1)
useGetV5DashboardChain(30-39)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsx (1)
apps/dashboard/src/@/hooks/chains/v5-adapter.ts (1)
useGetV5DashboardChain(30-39)
apps/dashboard/src/@/hooks/chains/v5-adapter.ts (1)
apps/playground-web/src/hooks/chains.ts (1)
useAllChainsData(17-39)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx (1)
apps/dashboard/src/@/hooks/chains/v5-adapter.ts (1)
useV5DashboardChain(14-28)
⏰ 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). (8)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Build Packages
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Lint Packages
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Unit Tests
- GitHub Check: Analyze (javascript)
🔇 Additional comments (10)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsx (1)
27-27: Good move: centralizing chain resolution via v5 adapterSwitching to useGetV5DashboardChain removes scattered defineChain calls and should reliably include custom/hidden chain metadata (custom RPCs) from idToChain. This aligns with MNY-115.
Also applies to: 44-44
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page.client.tsx (1)
20-20: Hook adoption looks solidDeriving Chain via useV5DashboardChain keeps behavior consistent with NFT flow and centralizes v5 dashboard chain logic.
Also applies to: 97-98
apps/dashboard/src/@/hooks/chains/v5-adapter.ts (1)
30-39: Nice addition: get-by-id helper for v5 dashboard chainsReturning a memoized function keeps call sites ergonomic and avoids repeating idToChain wiring.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx (5)
35-56: Good refactor: centralized chain resolution for all token flowsReplacing inline defineChain with useGetV5DashboardChain reduces duplication and ensures custom/hidden network RPCs are respected consistently across deploy and interactions.
79-86: OK: contract retrieval now uses resolved ChaingetContract now binds to the v5 dashboard chain object, which should prevent RPC mismatches on custom chains.
354-361: Verify token units for claimTo to avoid fractional/rounding issuesownerSupplyTokens can be fractional based on percentages. Depending on thirdweb’s ERC20 Drop API, claimTo may expect human-readable units or wei. Please confirm and, if needed, convert via toUnits with token decimals and round down. I can patch this, but wanted to validate expected units first.
55-56: Sanity check: ensure custom chain metadata is loaded before calling getChainIf idToChain hasn't resolved yet, getChain may lack custom RPCs. If we see sporadic “eth_getCode” failures on hidden networks, we should gate deploy buttons until useAllChainsData has hydrated. I can add a hook-provided isReady flag and wire it up here.
Also applies to: 114-115, 249-250
1-1: All directdefineChainusages removed – no findingsI searched the entire
apps/dashboard/src/appdirectory for any occurrences ofdefineChain(ordefineDashboardChain(in TypeScript/TSX files and found none. No legacy chain definitions remain in the dashboard’s token or NFT flows.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx (2)
10-10: Imports look correct and respect lint rulestype-only ThirdwebClient import and v5 chain hook import conform to project linting.
Also applies to: 38-38
312-313: Good: derive Chain once and reuse across childrenuseV5DashboardChain(Number(...)) gives TokenProvider a consistent Chain object for custom chains.
Merge activity
|
…hains (#7896) <!-- ## 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 introduces a new custom hook `useGetV5DashboardChain` and modifies existing components to utilize this hook for chain management, improving code clarity and reducing redundancy. ### Detailed summary - Added `useGetV5DashboardChain` hook in `v5-adapter.ts`. - Updated `LaunchNFT` component to use `useV5DashboardChain`. - Refactored `CreateTokenAssetPageUI` to use `useV5DashboardChain`. - Refactored `CreateNFTPage` to use `getChain` from `useGetV5DashboardChain`. - Refactored `CreateTokenAssetPage` to use `getChain` from `useGetV5DashboardChain`. > ✨ 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 - Refactor - Unified chain selection across NFT creation, NFT launch, and token creation flows using a single, consistent resolver. - Modernized internals for better compatibility with the latest chain data. - Bug Fixes - Improved reliability of chain selection during deployments and validations, reducing chances of selecting the wrong network. - More consistent behavior when switching chains in forms and launch steps. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
dda44c7 to
6caba38
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
🧹 Nitpick comments (4)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsx (4)
62-75: Harden chainId parsing to support CAIP-2 and prevent NaNUsing Number(params.chain) assumes a plain decimal or hex string and will produce NaN for inputs like "eip155:80087". Given custom/hidden chains often come through various formats, parse defensively and fail fast with a clear error.
Apply this diff within the selected lines:
- function getDeployedContract(params: { chain: string }) { - const chain = getChain(Number(params.chain)); + function getDeployedContract(params: { chain: string }) { + const chain = getChain(parseChainId(params.chain));Add this helper once in the module (outside selected lines):
// tolerant parser: decimal, hex, or CAIP-2 (eip155:<id>) function parseChainId(input: string | number): number { if (typeof input === "number") return input; const trimmed = input.trim(); const maybeId = trimmed.includes(":") ? trimmed.split(":").pop()! : trimmed; const id = Number(maybeId); if (!Number.isFinite(id) || id <= 0) { throw new Error(`Invalid chain id: "${input}"`); } return id; }Verification: please try with "80087", 80087, "0x138A7" (hex for 80087), and "eip155:80087" to ensure all resolve identically through useGetV5DashboardChain.
87-100: Same parsing robustness needed hereMirror the safer parsing when resolving the deployment chain to avoid silent NaN issues for custom networks.
Apply this diff within the selected lines:
- const chain = getChain(Number(collectionInfo.chain)); + const chain = getChain(parseChainId(collectionInfo.chain));
141-149: Ensure chainId type is numeric when adding contract to projectYou coerce to number for analytics (Line 133) but pass collectionInfo.chain (string) to addContractToProject. If the mutation expects a number, this can cause subtle bugs in cache keys or backend validation.
Apply this diff:
- chainId: collectionInfo.chain, + chainId: Number(collectionInfo.chain),If the mutation type already accepts string | number, still prefer a number here for consistency with reportContractDeployed and to keep query keys stable.
62-75: Surface friendlier error messages when chain resolution failsIf useGetV5DashboardChain cannot resolve a chain (e.g., missing custom network in local storage), the raw error will bubble up. Wrap resolution with a helpful message that hints at fixing the custom network configuration.
You can minimally wrap the calls:
- const chain = getChain(parseChainId(params.chain)); + let chain; + try { + chain = getChain(parseChainId(params.chain)); + } catch (err) { + throw new Error( + "Failed to resolve selected network. Please verify your custom network settings and try again.", + ); + }Repeat the same pattern in handleContractDeploy for collectionInfo.chain.
Also applies to: 87-100
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
apps/dashboard/src/@/hooks/chains/v5-adapter.ts(2 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsx(4 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx(4 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx(5 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page.client.tsx(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- apps/dashboard/src/@/hooks/chains/v5-adapter.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page-impl.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{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
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-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)/tokens/create/nft/create-nft-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)/tokens/create/nft/create-nft-page.tsx
🧠 Learnings (3)
📚 Learning: 2025-06-06T23:46:08.795Z
Learnt from: MananTank
PR: thirdweb-dev/js#7298
File: apps/dashboard/src/app/nebula-app/move-funds/move-funds.tsx:424-424
Timestamp: 2025-06-06T23:46:08.795Z
Learning: The thirdweb project has an ESLint rule that restricts direct usage of `defineChain`. When it's necessary to use `defineChain` directly, it's acceptable to disable the rule with `// eslint-disable-next-line no-restricted-syntax`.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.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)/tokens/create/nft/create-nft-page.tsx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.
Applied to files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Lint Packages
- GitHub Check: Unit Tests
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsx (2)
27-27: Good move: centralize chain resolution via v5 adapter hookReplacing ad-hoc chain resolution with a single hook is a solid step toward consistency across dashboard flows.
44-44: Hook usage looks correctStoring the resolver once per render and calling it where needed keeps things simple and avoids repeated lookups. No issues here.
| import { revalidatePathAction } from "@/actions/revalidate"; | ||
| import { reportContractDeployed } from "@/analytics/report"; | ||
| import type { Team } from "@/api/team/get-team"; | ||
| import { useGetV5DashboardChain } from "@/hooks/chains/v5-adapter"; |
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.
💡 Verification agent
🧩 Analysis chain
Double-check hook export and RPC source for custom chains (Freeq 80087)
To ensure MNY-115 is fully addressed, verify that useGetV5DashboardChain returns a chain whose rpc array prioritizes the user-provided RPC (e.g., https://rpc.testnet.superfreeq.com/) rather than a thirdweb aggregator URL for hidden/custom networks. This was the root cause of batched getCode failures.
Run this quick repo inspection to confirm the hook’s export and the RPC behavior:
🏁 Script executed:
#!/bin/bash
# Verify the hook is a named export
fd v5-adapter.ts
rg -nP 'export\s+(const|function)\s+useGetV5DashboardChain' -n
# Inspect how RPCs are selected/constructed inside the hook
rg -n 'rpc' $(fd v5-adapter.ts)Length of output: 305
🏁 Script executed:
#!/bin/bash
file="apps/dashboard/src/@/hooks/chains/v5-adapter.ts"
echo "===== Lines 1-200 of $file ====="
sed -n '1,200p' "$file"
echo ""
echo "===== Case-insensitive search for 'rpc' ====="
rg -n -i 'rpc' "$file" || echo "No matches for 'rpc'"
echo ""
echo "===== Search for 'url' ====="
rg -n 'url' "$file" || echo "No matches for 'url'"Length of output: 2386
🏁 Script executed:
#!/bin/bash
# Locate defineDashboardChain implementation
file=$(fd defineDashboardChain.ts)
echo "=== File: $file ==="
sed -n '1,200p' "$file"
echo ""
echo "=== Search for 'rpc' occurrences ==="
rg -n 'rpc' "$file" || echo "No 'rpc' references found"
echo ""
echo "=== Search for array of RPCs or custom RPC logic ==="
rg -nP 'rpc[s]?[\s]*=' "$file" || echo "No RPC assignment pattern found"
echo ""
echo "=== Search for user-provided RPC override handling ==="
rg -nP 'custom|override|user' "$file" || echo "No custom RPC override logic found"Length of output: 1665
RPC override not implemented in defineDashboardChain
We confirmed that:
useGetV5DashboardChainis correctly exported (apps/dashboard/src/@/hooks/chains/v5-adapter.ts:30).defineDashboardChain(apps/dashboard/src/@/lib/defineDashboardChain.ts:15–20) always falls back to a single default RPC URL (https://${chainId}.rpc.${PROD_OR_DEV_URL}) and does not include or prioritize any user-provided/custom RPCs.
To fully address MNY-115 and avoid batched getCode failures on hidden/custom networks, you need to update defineDashboardChain to:
- Accept an optional user-provided RPC override (e.g.
https://rpc.testnet.superfreeq.com/). - Construct the resulting chain’s
rpcfield as an array that places the override first, followed by the default/aggregator URLs.
Locations to update:
- apps/dashboard/src/@/lib/defineDashboardChain.ts (around the
return defineChain({ … rpc: … })block) - Ensure
useGetV5DashboardChainconsumers pass through any available override intodefineDashboardChain.
Please implement these changes so that custom RPCs are prioritized over the default aggregator URLs.
🤖 Prompt for AI Agents
In apps/dashboard/src/@/lib/defineDashboardChain.ts (around the defineChain
return block) and update usages in
apps/dashboard/src/@/hooks/chains/v5-adapter.ts (and any consumers) —
defineDashboardChain currently always builds a single default RPC URL; change
its signature to accept an optional rpcOverride string (or array) and set the
chain.rpc field to an array that places the override(s) first followed by the
existing default/aggregator URLs (de-duplicate if needed), then update
useGetV5DashboardChain to accept/forward any available override into
defineDashboardChain so consumers pass the custom RPC through and it is
prioritized over defaults.

PR-Codex overview
This PR enhances the
v5-adapterby introducing new hooks for managing chains in the dashboard. It updates several components to utilize these hooks, improving the handling of chain data across the application.Detailed summary
useGetV5DashboardChainanduseGetV5DashboardChainhooks inv5-adapter.ts.defineChainwith the new hooks in multiple components.LaunchNFT,CreateTokenAssetPageUI,CreateNFTPage, andCreateTokenAssetPageto use the new hooks for chain management.Summary by CodeRabbit
Refactor
Bug Fixes