-
Notifications
You must be signed in to change notification settings - Fork 535
Add Contract layout in team/project #7152
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
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThis update introduces a project-scoped contract dashboard experience by propagating a Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant RoutePage
participant API
participant SharedComponent
participant ContractComponent
User->>RoutePage: Access contract page (with team/project slugs)
RoutePage->>API: Fetch team/project by slug
API-->>RoutePage: Return team/project (or 404)
RoutePage->>SharedComponent: Render with contractAddress, chainIdOrSlug, projectMeta
SharedComponent->>API: Fetch contract info (with projectMeta)
API-->>SharedComponent: Return contract info
alt Contract supported
SharedComponent->>ContractComponent: Render with contract info, projectMeta
else Not supported
SharedComponent->>User: Redirect or 404
end
Suggested labels
Suggested reviewers
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
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 ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #7152 +/- ##
=======================================
Coverage 55.68% 55.68%
=======================================
Files 904 904
Lines 58324 58324
Branches 4113 4113
=======================================
Hits 32476 32476
Misses 25743 25743
Partials 105 105
🚀 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: 20
🔭 Outside diff range comments (4)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/page.tsx (1)
3-8
:⚠️ Potential issue
params
should not be typed as aPromise
Next.js’
PageProps
shape providesparams
synchronously – it is already the plain object extracted from the route, not a promise.
Typing it asPromise<…>
forces every consumer toawait
something that is never asynchronous, producing a type-error at compile time and signalling a misleading contract to future maintainers.-export default async function Page(props: { - params: Promise<{ - contractAddress: string; - chain_id: string; - }>; -}) { - const params = await props.params; +export default async function Page(props: { + params: { + contractAddress: string; + chain_id: string; + }; +}) { + const { params } = props;apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/page.tsx (1)
4-8
:⚠️ Potential issueIncorrect
Promise
typing forparams
(same issue as settings page)
params
is synchronous; typing it as a promise causes type errors and unnecessaryawait
.-export default async function Page(props: { - params: Promise<{ +export default async function Page(props: { + params: { contractAddress: string; chain_id: string; - }>; + }; }) { - const params = await props.params; + const { params } = props;apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/events/events-feed.tsx (1)
88-103
:⚠️ Potential issueSelecting “All” events never updates the UI
eventTypes
does not include"all"
, therefore this guard prevents both
router.push
andsetSelectedEvent
from running when the user chooses “All”.- if (eventTypes.includes(val)) { + if (val === "all" || eventTypes.includes(val)) {Without this change the dropdown appears selectable but does nothing, which is a UX bug.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/layout.tsx (1)
8-15
: 🛠️ Refactor suggestion
params
should not be aPromise
– mismatched Next.js typeIn Next 13/14 route segments,
Layout
receivesprops.params
as a plain object, not aPromise
.
Declaring andawait
-ing it complicates the type signature and may mask real type errors elsewhere.-export default async function Layout(props: { - params: Promise<{ +export default async function Layout(props: { + params: { contractAddress: string; chain_id: string; }; children: React.ReactNode; }) { - const params = await props.params; + const params = props.params;Recommend aligning the declaration; TS will then surface issues at compile-time instead of runtime.
♻️ Duplicate comments (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/ContractNFTPage.client.tsx (1)
4-4
: Same import path concern as previous file.This file has the same deeply nested import path issue for
ProjectMeta
. Consider the same recommendation to centralize type definitions for better maintainability.
🧹 Nitpick comments (39)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/components/nfts-owned.tsx (1)
5-5
: Consider using an absolute import path for better maintainability.The relative import path is very deep (6 levels) and creates tight coupling between components. This makes the codebase fragile to directory structure changes.
Consider using an absolute import or creating a shared types file:
-import type { ProjectMeta } from "../../../../../../team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types"; +import type { ProjectMeta } from "@/types/project-meta";Or create a shared types barrel export to reduce the import complexity.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/ClaimConditions.client.tsx (1)
4-4
: Consider using an absolute import path for better maintainability.The relative import path is very deep and creates tight coupling. This is the same issue present across multiple files in this PR.
Consider centralizing the
ProjectMeta
type in a shared location:-import type { ProjectMeta } from "../../../../../team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types"; +import type { ProjectMeta } from "@/types/project-meta";apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/AccountSigners.client.tsx (1)
4-4
: Consider using an absolute import path for better maintainability.This is the same deep relative import path issue seen across multiple files in this PR. Consider creating a shared types module to reduce coupling and improve maintainability.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/ContractEditModulesPage.client.tsx (1)
4-4
: Consider using a more maintainable import path.The relative import path with multiple "../" segments could be fragile if the directory structure changes. Consider using an absolute import or creating a shared types barrel export.
For better maintainability, consider:
-import type { ProjectMeta } from "../../../../../team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types"; +import type { ProjectMeta } from "@/app/types/project"; // or similar absolute pathHowever, since this pattern appears consistent across the codebase refactor, this change can be addressed in a follow-up cleanup.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/sources/page.tsx (1)
1-19
: Good refactor, but note parameter inconsistency across shared components.The extraction to
SharedContractSourcesPage
is well-implemented and follows the same pattern as other contract pages. However, there's an architectural inconsistency worth noting: this shared component expectsteamId: undefined
while other shared components (likeSharedModulesPage
) expectprojectMeta: ProjectMeta | undefined
.Consider standardizing the parameter structure across all shared contract page components to use either
projectMeta
orteamId
consistently. This would improve maintainability and reduce confusion.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/ContractEnglishAuctionsPage.client.tsx (1)
4-4
: Consider centralizing type definitions.The deeply nested import path for
ProjectMeta
could be improved for maintainability. Consider moving shared types likeProjectMeta
to a more central location (e.g.,src/types/
or similar) to reduce coupling and improve discoverability.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/modules/page.tsx (1)
10-10
: Consider clarifying variable naming for better maintainability.The variable is named
team
but you're callinggetProject()
. Based on the usage where you accessteam.id
andteam.slug
, it appears the Project object contains team information. For clarity, consider either:
- Renaming the variable to
project
if it represents a project object containing team info- Or updating the comment to clarify that
getProject
returns team metadata- const team = await getProject(params.team_slug, params.project_slug); + const project = await getProject(params.team_slug, params.project_slug); - if (!team) { + if (!project) { - teamId: team.id, - teamSlug: team.slug, + teamId: project.teamId, // or project.team.id depending on API structure + teamSlug: project.teamSlug, // or project.team.slug depending on API structureAlso applies to: 23-24
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/events/page.tsx (1)
10-10
: Consider renaming variable for clarity.The variable is named
team
but stores the result ofgetProject()
. While the usage suggests the Project object contains team information, this naming could be confusing for future maintainers.Consider renaming for clarity:
- const team = await getProject(params.team_slug, params.project_slug); + const project = await getProject(params.team_slug, params.project_slug);And update the references accordingly:
- if (!team) { + if (!project) { notFound(); } return ( <SharedEventsPage params={{ contractAddress: params.contractAddress, chainIdOrSlug: params.chainIdOrSlug, projectMeta: { projectSlug: params.project_slug, - teamId: team.id, - teamSlug: team.slug, + teamId: project.teamId, // or project.team.id depending on structure + teamSlug: project.teamSlug, // or project.team.slug }, }} /> );apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/code/page.tsx (1)
9-10
: Consider renaming variable for clarity.The variable
team
actually contains project data fromgetProject()
. Consider renaming it toproject
for better code readability.- const team = await getProject(params.team_slug, params.project_slug); + const project = await getProject(params.team_slug, params.project_slug);And update the reference on line 23:
- teamId: team.id, + teamId: project.id,And line 24:
- teamSlug: team.slug, + teamSlug: project.slug,apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/account-permissions/page.tsx (1)
3-3
: Consider using absolute imports to improve maintainability.The relative import path
../../../../../../../(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/shared-account-permissions-page
is very long and brittle to refactoring. Consider using absolute imports or path aliases.-import { SharedContractAccountPermissionsPage } from "../../../../../../../(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/shared-account-permissions-page"; +import { SharedContractAccountPermissionsPage } from "@/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/shared-account-permissions-page";apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx (1)
3-3
: Consider using absolute imports to improve maintainability.The relative import path is very long and brittle to refactoring. Consider using absolute imports or path aliases for better maintainability.
-import { SharedNFTPage } from "../../../../../../../(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/shared-nfts-page"; +import { SharedNFTPage } from "@/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/shared-nfts-page";apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/[tokenId]/page.tsx (2)
14-14
: Fix confusing variable namingThe variable name
team
is misleading sincegetProject()
returns a project object, not a team. This could cause confusion for future developers.- const team = await getProject(params.team_slug, params.project_slug); + const project = await getProject(params.team_slug, params.project_slug); - if (!team) { + if (!project) {Also applies to: 16-16
26-30
: Update variable reference in ProjectMeta constructionFollowing the variable naming fix above, update the reference in the
projectMeta
object.projectMeta: { projectSlug: params.project_slug, - teamId: team.id, - teamSlug: team.slug, + teamId: project.id, + teamSlug: project.slug, },apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/settings/page.tsx (1)
3-3
: Consider refactoring the long import path for maintainability.The import path
../../../../../../../(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/shared-settings-page
is quite long and fragile. Consider using a path alias or moving shared components to a more accessible location.// Consider using a path alias like: import { SharedContractSettingsPage } from "@/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/shared-settings-page";apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/account/page.tsx (1)
3-3
: Same import path maintainability concern.Similar to other files in this refactor, consider using path aliases for the long relative import.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/page.tsx (2)
1-3
: Replace brittle deep-relative import with an absolute/alias pathNine “
../
” segments are easy to get wrong (and they already differ from the depth used in neighbouring pages).
Using the existing@/
alias (or introducing one) avoids future breakage when folders move.-import { SharedContractOverviewPage } from "../../../../../../(dashboard)/(chain)/[chain_id]/[contractAddress]/shared-overview-page"; +import { SharedContractOverviewPage } from "@/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/shared-overview-page";
16-29
: Memoise the team lookup to avoid N+1 requests across sibling pagesEvery contract sub-page repeats:
const team = await getTeamBySlug(params.team_slug);When a user navigates between pages, the same network request is made again.
WrappinggetTeamBySlug
withcache()
from React 18 (or re-exporting a cached variant) will give a free in-memory response and speed up navigation:// in @/api/team.ts -import { getAuthToken } from "./auth"; +import { getAuthToken } from "./auth"; +import { cache } from "react"; -export async function getTeamBySlug(slug: string) { +export const getTeamBySlug = cache(async (slug: string) => { ... -} +});apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/(marketplace)/english-auctions/page.tsx (1)
6-10
: Consistent handling ofparams
Same remark as in the claim-conditions page: if
params
is not actually aPromise
here, drop theawait
and adjust the type.
Keeping the signature consistent across the new team/project pages will avoid confusion.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/claim-conditions/page.tsx (1)
10-10
: Consider renaming the variable for clarity.The variable is named
team
but thegetProject
API call returns project data according to the function signature. Consider renaming it toproject
for consistency:- const team = await getProject(params.team_slug, params.project_slug); + const project = await getProject(params.team_slug, params.project_slug);And update the subsequent references accordingly.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/Analytics.tsx (1)
14-14
: Consider using an absolute import path.The relative import path is quite long and brittle. Consider using an absolute import if the types are commonly used across the dashboard:
-import type { ProjectMeta } from "../../../../../../team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types"; +import type { ProjectMeta } from "@/types/project"; // or similar absolute pathapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/explorer/page.tsx (1)
10-10
: Consider renaming the variable for clarity.Same issue as in the claim-conditions page - the variable is named
team
but contains project data. For consistency and clarity:- const team = await getProject(params.team_slug, params.project_slug); + const project = await getProject(params.team_slug, params.project_slug);And update lines 23-24 accordingly.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-table.tsx (2)
19-19
: Extremely long relative import path – consider using a path aliasThe multi-
../
path is brittle; a single directory move will break the import and makes the location ofProjectMeta
non-obvious. Add atsconfig.json
/jest
path alias (e.g.@/types/ProjectMeta
) so consumers can import it concisely and safely.
99-107
:onRowClick
URL building duplicates routing logicHard-coding the paths in multiple components risks divergence from the canonical router helpers. Consider centralising URL creation in
useDashboardRouter
(e.g.router.toContractAccount(projectMeta, chainSlug, row.account)
) to avoid future inconsistencies and to automatically encode path params.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/page.tsx (1)
1-1
: Remove empty import – it produces an unused-import lint error
import {} from "next/navigation";
imports nothing and is unnecessary.-import {} from "next/navigation";
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
30-30
: Optimize useEffect dependencies for better performanceThe current dependency array
[router, props]
is too broad. Theprops
object reference changes on every render, causing unnecessary effect re-runs.Consider destructuring the specific props needed in the dependency array:
- }, [router, props]); + }, [router, props.contract.chain.id, props.contract.address, props.projectMeta]);This ensures the effect only runs when the actual values change, not when the props object reference changes.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/shared-english-auctions-page.tsx (1)
16-28
: Optimize performance with parallel data fetching.Unlike other shared components in this PR, this implementation fetches the account sequentially after contract info rather than in parallel. This could impact performance.
Consider using
Promise.all
for parallel fetching to match the pattern used in other shared components:- const info = await getContractPageParamsInfo({ - contractAddress: params.contractAddress, - chainIdOrSlug: params.chainIdOrSlug, - teamId: params.projectMeta?.teamId, - }); - - if (!info) { - notFound(); - } - - const twAccount = await getRawAccount(); + const [twAccount, info] = await Promise.all([ + getRawAccount(), + getContractPageParamsInfo({ + contractAddress: params.contractAddress, + chainIdOrSlug: params.chainIdOrSlug, + teamId: params.projectMeta?.teamId, + }), + ]); + + if (!info) { + notFound(); + }This matches the performance optimization pattern used in
shared-direct-listings-page.tsx
(lines 17-24).apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/shared-split-page.tsx (1)
28-28
: Use consistent variable naming across shared components.The variable
twAccount
should be namedaccount
for consistency with other shared contract components.- const twAccount = await getRawAccount(); + const account = await getRawAccount();And update the references accordingly:
- isLoggedIn={!!twAccount} + isLoggedIn={!!account}- <ContractSplitPage contract={clientContract} isLoggedIn={!!twAccount} /> + <ContractSplitPage contract={clientContract} isLoggedIn={!!account} />apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/shared-account-permissions-page.tsx (1)
8-21
: Parameter structure inconsistency across shared components.The parameter structure here differs from
SharedContractTokensPage
- this component takesprojectMeta
as a parameter and extractsteamId
from it, while the tokens shared page takesteamId
directly. Consider standardizing the parameter structure across all shared components for consistency.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/shared-overview-page.tsx (2)
1-3
: Import path with nested dynamic segments is fragileThe relative path to
types.ts
walks through several dynamic route folders.
Changes in folder depth or renaming any route segment will silently break the import and TypeScript will not resolve it until build time.-import type { ProjectMeta } from "../../../../team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types"; +// ✅ consider using the path alias already configured for app code, e.g.: +import type { ProjectMeta } from "@/app/types/project-meta";Using a ts-config path alias (e.g.
@/app/...
) improves resiliency and readability.
57-61
: Silent swallow ofPublishedBy
errors loses debugging signal
ErrorBoundary
withfallback={null}
hides all publisher-related errors without
logging, making production issues hard to trace.-<ErrorBoundary fallback={null}> +<ErrorBoundary + fallback={null} + onError={(err) => { + // eslint-disable-next-line no-console -- server-only diagnostic + console.error("[ContractOverview] PublishedBy failed:", err); + }} +>Adding a minimal
onError
callback (or Sentry capture) preserves observability without breaking the end-user experience.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/shared-nfts-token-page.tsx (1)
41-45
: Minor optimisation: parallelise account and metadata fetch
getAuthTokenWalletAddress
andgetRawAccount
are already parallelised, but
getContractPageMetadata
(non-localhost branch) could also be added to the
Promise.all
above to save one round-trip latency.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/analytics/shared-analytics-page.tsx (2)
28-35
: Nit: Destructuring names mismatch hampers readability
getSelectors
returns{ writeFnSelectorToName, eventSelectorToName }
but the
result is unpacked into variables with the same names; the “Record” suffix is
added only at the prop level. Consider harmonising names:- { eventSelectorToName, writeFnSelectorToName }, + { eventSelectorToName: eventSelectorToNameRecord, + writeFnSelectorToName: writeFnSelectorToNameRecord },and pass the variables with identical names.
This avoids accidental shadowing when the component grows.
53-70
: Guard against missingname
in ABI itemsSome ABI entries (e.g. fallback / receive functions) lack
name
; current code
would assignundefined
, producing a selector→undefined
mapping.- writeFnSelectorToName[toFunctionSelector(item)] = item.name; + if (item.name) { + writeFnSelectorToName[toFunctionSelector(item)] = item.name; + }The same applies to events.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/events/events-feed.tsx (1)
54-57
: URL construction logic duplicated & fragile – extract a helper
contractRootPath
is recomputed in multiple places (EventsFeed
,EventsFeedItem
,
MarketplaceDetails
, etc.).
Centralising this logic will:
- Prevent subtle mismatches (
/contract
vs. empty string).- Reduce boilerplate.
Example:
// utils/paths.ts export const getContractRoot = (meta?: ProjectMeta) => meta ? `/team/${meta.teamSlug}/${meta.projectSlug}/contract` : "";Then:
-const contractRootPath = projectMeta - ? `/team/${projectMeta.teamSlug}/${projectMeta.projectSlug}/contract` - : ""; +const contractRootPath = getContractRoot(projectMeta);Also applies to: 191-194
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/MarketplaceDetails.tsx (1)
300-308
: Hard-coded URL pieces – rely on extracted helperSee previous comment: replace inline interpolation with the shared
getContractRoot()
helper to keep path generation consistent.-const directListingsHref = `${contractRootPath}/${chainSlug}/${contractAddress}/direct-listings`; -const englishAuctionsHref = `${contractRootPath}/${chainSlug}/${contractAddress}/english-auctions`; +const base = `${getContractRoot(projectMeta)}/${chainSlug}/${contractAddress}`; +const directListingsHref = `${base}/direct-listings`; +const englishAuctionsHref = `${base}/english-auctions`;apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/shared-layout.tsx (1)
196-210
: Minor copy edit – double space & slug vs chain-ID wordingThe fallback metadata description currently renders with two spaces (
"contract on"
) and always says “Chain ID” even when a slug such aspolygon
is supplied:description: `View tokens, transactions, balances, source code, and analytics for the ${contractDisplayName} smart contract on ${cleanedChainName}`; ... description: `View tokens, transactions, balances, source code, and analytics for the smart contract on Chain ID ${params.chainIdOrSlug}`,Consider tightening the string and conditionally wording the identifier:
- description = `View tokens, transactions, balances, source code, and analytics for the ${contractDisplayName} smart contract on ${cleanedChainName}`; + description = `View tokens, transactions, balances, source code, and analytics for the ${contractDisplayName} smart contract on ${cleanedChainName}.`; ... - description: `View tokens, transactions, balances, source code, and analytics for the smart contract on Chain ID ${params.chainIdOrSlug}`, + description: `View tokens, transactions, balances, source code, and analytics for this smart contract on ${params.chainIdOrSlug}.`,A tiny tweak, but it improves the professionalism of SEO snippets.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/cross-chain/shared-cross-chain-page.tsx (3)
129-170
: Skip the home chain before firing 9 extra RPC calls
defaultChains
always includes the current chain, yet it is filtered after the
Promise.all
, meaning we still perform an unnecessaryeth_getCode
on the chain we
already have data for.- await Promise.all( - defaultChains.map(async (c) => { + await Promise.all( + defaultChains + .filter((c) => c !== serverContract.chain.id) // avoid redundant call + .map(async (c) => {Small change, but it saves one network round-trip per request and reduces noise in
RPC metrics.
60-68
: Suppressing all errors can hide genuine connectivity issuesThe empty
catch {}
aroundgetDeployedCloneFactoryContract
swallows
network/ABI errors that might explain missing data later on.
At minimum, log a warning withconsole.warn
(server side) or return a typed
Result
object so callers can act accordingly.
181-185
: Early return bypasses fetch-error handlingWhen
fetchPublishedContractsFromDeploy
fails we fall back to the
“NoCrossChainPrompt” without differentiating between “metadata not found”
and “network error / rate limit”. Users may mistake transient errors for an
absence of cross-chain capability.Consider distinguishing:
} catch (e) { logger.error(e); return <ErrorState message="Unable to fetch deploy metadata. Please retry." />; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (107)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/ContractDirectListingsPage.client.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/shared-direct-listings-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/ContractEnglishAuctionsPage.client.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/shared-english-auctions-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/NFTCards.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/contract-page-layout.client.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/contract-page-layout.tsx
(5 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx
(4 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageSidebarLinks.ts
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/AccountSigners.client.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/shared-account-permissions-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/AccountPage.client.tsx
(4 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/AccountPage.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/components/nfts-owned.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/shared-account-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/AccountsPage.client.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/AccountsPage.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-table.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/shared-accounts-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/analytics/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/analytics/shared-analytics-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/ClaimConditions.client.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/shared-claim-conditions-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/code/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/code/shared-code-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/cross-chain/data-table.tsx
(5 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/cross-chain/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/cross-chain/shared-cross-chain-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/events/events-feed.tsx
(5 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/events/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/events/shared-events-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/explorer/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/explorer/shared-explorer-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/layout.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/ContractEditModulesPage.client.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/shared-modules-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/ContractNFTPage.client.tsx
(4 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/ContractNFTPage.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/TokenIdPage.client.tsx
(4 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/shared-nfts-token-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/token-id.tsx
(4 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/table.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/shared-nfts-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/opengraph-image.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/ContractOverviewPage.tsx
(7 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/Analytics.tsx
(4 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/BuildYourApp.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/ContractChecklist.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/LatestEvents.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/MarketplaceDetails.tsx
(11 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/NFTDetails.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/PermissionsTable.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/contract-overview-page.client.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/ContractPermissionsPage.client.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/ContractPermissionsPage.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/shared-permissions-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/ContractProposalsPage.client.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/shared-proposals-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/shared-settings-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/shared-layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/shared-overview-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/sources/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/sources/shared-sources-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/ContractSplitPage.client.tsx
(3 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/shared-split-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/page.tsx
(2 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/shared-page.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/DeployedContractsPage.tsx
(3 hunks)apps/dashboard/src/app/(app)/api/lib/getAuthToken.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/page.tsx
(3 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/connect/account-abstraction/factories/page.tsx
(5 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/(marketplace)/direct-listings/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/(marketplace)/english-auctions/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/account-permissions/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/account/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/accounts/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/analytics/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/claim-conditions/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/code/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/cross-chain/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/events/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/explorer/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/modules/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/[tokenId]/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/permissions/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/proposals/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/settings/page.tsx
(1 hunks)
⛔ Files not processed due to max files limit (9)
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/sources/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/split/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/tokens/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/utils.ts
- apps/dashboard/src/components/contract-components/tables/cells.tsx
- apps/dashboard/src/components/contract-components/tables/contract-table.stories.tsx
- apps/dashboard/src/components/contract-components/tables/contract-table.tsx
- apps/dashboard/src/components/smart-wallets/AccountFactories/factory-contracts.tsx
🧰 Additional context used
🧠 Learnings (8)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/(marketplace)/direct-listings/page.tsx (1)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/permissions/page.tsx (1)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/page.tsx (1)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/analytics/page.tsx (1)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/code/page.tsx (1)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx (1)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/account/page.tsx (1)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/explorer/page.tsx (1)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
🧬 Code Graph Analysis (77)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/opengraph-image.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts (1)
getContractPageParamsInfo
(8-46)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/ContractPermissionsPage.client.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/ContractDirectListingsPage.client.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
RedirectToContractOverview
(9-33)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/shared-split-page.tsx (1)
SharedContractSplitPage
(9-49)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/shared-account-permissions-page.tsx (1)
SharedContractAccountPermissionsPage
(8-45)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/(marketplace)/direct-listings/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/team.ts (1)
getTeamBySlug
(11-30)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/shared-direct-listings-page.tsx (1)
SharedDirectListingsPage
(9-54)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/ContractSplitPage.client.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
RedirectToContractOverview
(9-33)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/sources/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/sources/shared-sources-page.tsx (1)
SharedContractSourcesPage
(5-19)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/ContractEditModulesPage.client.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
RedirectToContractOverview
(9-33)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/ContractEnglishAuctionsPage.client.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
RedirectToContractOverview
(9-33)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/claim-conditions/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/projects.ts (1)
getProject
(29-48)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/shared-claim-conditions-page.tsx (1)
SharedClaimConditionsPage
(10-73)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/components/nfts-owned.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/permissions/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/projects.ts (1)
getProject
(29-48)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/shared-permissions-page.tsx (1)
SharedPermissionsPage
(9-54)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/shared-permissions-page.tsx (1)
SharedPermissionsPage
(9-54)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/shared-claim-conditions-page.tsx (1)
SharedClaimConditionsPage
(10-73)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/ContractProposalsPage.client.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
RedirectToContractOverview
(9-33)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/account-permissions/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/team.ts (1)
getTeamBySlug
(11-30)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/shared-account-permissions-page.tsx (1)
SharedContractAccountPermissionsPage
(8-45)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/BuildYourApp.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/shared-settings-page.tsx (1)
SharedContractSettingsPage
(10-56)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/TokenIdPage.client.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
RedirectToContractOverview
(9-33)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/AccountsPage.client.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
RedirectToContractOverview
(9-33)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/AccountsPage.tsx (1)
AccountsPage
(17-52)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/shared-nfts-page.tsx (1)
SharedNFTPage
(10-62)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/shared-modules-page.tsx (1)
SharedModulesPage
(10-55)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/AccountPage.client.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
RedirectToContractOverview
(9-33)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/shared-accounts-page.tsx (1)
SharedAccountsPage
(9-57)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/AccountSigners.client.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
RedirectToContractOverview
(9-33)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/shared-account-page.tsx (1)
SharedContractAccountPage
(9-59)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/sources/shared-sources-page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts (1)
getContractPageParamsInfo
(8-46)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/shared-overview-page.tsx (1)
SharedContractOverviewPage
(10-64)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/shared-proposals-page.tsx (1)
SharedContractProposalsPage
(9-48)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-table.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/ContractNFTPage.client.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
RedirectToContractOverview
(9-33)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/events/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/projects.ts (1)
getProject
(29-48)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/events/shared-events-page.tsx (1)
SharedEventsPage
(6-30)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/shared-nfts-token-page.tsx (1)
SharedNFTTokenPage
(11-79)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/PermissionsTable.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/contract-page-layout.client.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/ClaimConditions.client.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
RedirectToContractOverview
(9-33)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/ContractNFTPage.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/proposals/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/team.ts (1)
getTeamBySlug
(11-30)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/shared-proposals-page.tsx (1)
SharedContractProposalsPage
(9-48)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/(marketplace)/english-auctions/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/team.ts (1)
getTeamBySlug
(11-30)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/shared-english-auctions-page.tsx (1)
SharedEnglishAuctionsPage
(9-53)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/team.ts (1)
getTeamBySlug
(11-30)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/shared-overview-page.tsx (1)
SharedContractOverviewPage
(10-64)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/contract-page-layout.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/events/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/events/shared-events-page.tsx (1)
SharedEventsPage
(6-30)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/code/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/code/shared-code-page.tsx (1)
SharedCodePage
(8-47)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/table.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/shared-proposals-page.tsx (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts (1)
getContractPageParamsInfo
(8-46)apps/dashboard/src/app/(app)/account/settings/getAccount.ts (1)
getRawAccount
(11-38)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/ContractProposalsPage.client.tsx (1)
ContractProposalsPageClient
(10-40)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageMetadata.ts (1)
getContractPageMetadata
(30-32)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/explorer/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/explorer/shared-explorer-page.tsx (1)
SharedExplorerPage
(9-53)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/shared-account-permissions-page.tsx (4)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts (1)
getContractPageParamsInfo
(8-46)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/AccountSigners.client.tsx (1)
AccountSignersClient
(10-34)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageMetadata.ts (1)
getContractPageMetadata
(30-32)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/analytics/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/projects.ts (1)
getProject
(29-48)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/analytics/shared-analytics-page.tsx (1)
SharedAnalyticsPage
(10-51)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/shared-direct-listings-page.tsx (1)
SharedDirectListingsPage
(9-54)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/code/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/projects.ts (1)
getProject
(29-48)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/code/shared-code-page.tsx (1)
SharedCodePage
(8-47)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/cross-chain/data-table.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/api/lib/getAuthToken.ts (1)
apps/dashboard/src/@/constants/thirdweb-client.client.ts (1)
getClientThirdwebClient
(3-11)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/contract-overview-page.client.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/modules/page.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/shared-modules-page.tsx (1)
SharedModulesPage
(10-55)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts (1)
apps/dashboard/src/app/(app)/api/lib/getAuthToken.ts (1)
getUserThirdwebClient
(32-51)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/NFTDetails.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/shared-page.tsx (1)
SharedContractTokensPage
(12-50)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/AccountPage.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/components/nfts-owned.tsx (1)
NftsOwned
(14-51)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/LatestEvents.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/@3rdweb-sdk/react/hooks/useActivity.ts (1)
useActivity
(16-55)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/shared-modules-page.tsx (6)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts (1)
getContractPageParamsInfo
(8-46)apps/dashboard/src/app/(app)/account/settings/getAccount.ts (1)
getRawAccount
(11-38)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/ContractEditModulesPage.client.tsx (1)
ContractEditModulesPageClient
(10-40)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageMetadata.ts (1)
getContractPageMetadata
(30-32)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/utils.ts (1)
redirectToContractLandingPage
(5-18)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/page.tsx (1)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/shared-english-auctions-page.tsx (1)
SharedEnglishAuctionsPage
(9-53)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/[tokenId]/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/projects.ts (1)
getProject
(29-48)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/shared-nfts-token-page.tsx (1)
SharedNFTTokenPage
(11-79)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/shared-settings-page.tsx (4)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts (1)
getContractPageParamsInfo
(8-46)apps/dashboard/src/app/(app)/account/settings/getAccount.ts (1)
getRawAccount
(11-38)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageMetadata.ts (1)
getContractPageMetadata
(30-32)apps/dashboard/src/constants/addresses.ts (1)
DEFAULT_FEE_RECIPIENT
(7-8)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/token-id.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageSidebarLinks.ts (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/account/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/team.ts (1)
getTeamBySlug
(11-30)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/shared-account-page.tsx (1)
SharedContractAccountPage
(9-59)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/ContractChecklist.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/Analytics.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/accounts/page.tsx (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectContractPageParams
(1-6)apps/dashboard/src/@/api/team.ts (1)
getTeamBySlug
(11-30)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/shared-accounts-page.tsx (1)
SharedAccountsPage
(9-57)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/shared-split-page.tsx (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts (1)
getContractPageParamsInfo
(8-46)apps/dashboard/src/app/(app)/account/settings/getAccount.ts (1)
getRawAccount
(11-38)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/ContractSplitPage.client.tsx (1)
ContractSplitPageClient
(10-40)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageMetadata.ts (1)
getContractPageMetadata
(30-32)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/MarketplaceDetails.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/shared-english-auctions-page.tsx (5)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts (1)
getContractPageParamsInfo
(8-46)apps/dashboard/src/app/(app)/account/settings/getAccount.ts (1)
getRawAccount
(11-38)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/ContractEnglishAuctionsPage.client.tsx (1)
ContractEnglishAuctionsPageClient
(10-41)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageMetadata.ts (1)
getContractPageMetadata
(30-32)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/shared-claim-conditions-page.tsx (6)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts (1)
getContractPageParamsInfo
(8-46)apps/dashboard/src/app/(app)/account/settings/getAccount.ts (1)
getRawAccount
(11-38)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageMetadata.ts (1)
getContractPageMetadata
(30-32)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/ClaimConditions.client.tsx (1)
ClaimConditionsClient
(10-48)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/utils.ts (1)
redirectToContractLandingPage
(5-18)
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/NFTCards.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types.ts (1)
ProjectMeta
(8-12)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: Size
- GitHub Check: Analyze (javascript)
🔇 Additional comments (146)
apps/dashboard/src/app/(app)/api/lib/getAuthToken.ts (1)
32-51
: LGTM! Good API design improvement.The function signature change to accept a parameter object with optional
teamId
follows good practices and aligns well with the project-scoped functionality being introduced. The prioritization logic correctly handles explicitteamId
parameters while preserving the existing cookie-based fallback behavior.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/ContractPermissionsPage.client.tsx (2)
5-5
: LGTM! Proper type import.The import of
ProjectMeta
type uses the correct relative path and follows TypeScript best practices.
14-14
: LGTM! Clean prop threading.The addition of the optional
projectMeta
prop and its pass-through to the child component is implemented correctly and follows the established pattern for project-scoped functionality.Also applies to: 28-28
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/contracts/page.tsx (1)
45-46
: LGTM! Proper prop addition.The addition of
teamSlug
andprojectSlug
props toDeployedContractsPage
correctly uses the already available parameters and follows the established pattern for project-scoped functionality.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/opengraph-image.tsx (1)
24-28
: LGTM! Correct function signature update.The update to explicitly construct the parameter object with
chainIdOrSlug
andteamId: undefined
correctly matches the new function signature shown in the relevant code snippets. SettingteamId
toundefined
is appropriate for this route context which doesn't have project scope.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/components/nfts-owned.tsx (1)
11-11
: LGTM! Consistent project metadata integration.The addition of the optional
projectMeta
prop and its propagation toNFTCards
follows the established pattern for project-scoped routing support. The type safety is maintained with proper TypeScript annotations.Also applies to: 17-17, 30-30
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/ClaimConditions.client.tsx (1)
13-13
: LGTM! Proper project metadata propagation.The addition of the
projectMeta
prop and its forwarding toRedirectToContractOverview
enables project-scoped routing when claim conditions are unsupported. The conditional rendering logic correctly maintains the redirect behavior while adding project context.Also applies to: 32-37
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/AccountSigners.client.tsx (1)
12-12
: LGTM! Consistent project metadata integration.The
projectMeta
prop addition and its propagation toRedirectToContractOverview
maintains consistency with the broader architectural pattern. The conditional rendering logic correctly handles unsupported account permissions while preserving project context during redirects.Also applies to: 25-30
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/ContractSplitPage.client.tsx (2)
13-13
: LGTM! Consistent project metadata integration.The
projectMeta
prop addition and its propagation toRedirectToContractOverview
follows the established pattern. The conditional rendering correctly handles unsupported split contracts while maintaining project context.Also applies to: 26-31
34-39
:❌ Incorrect review comment
Consider passing projectMeta to ContractSplitPage if needed.
The
ContractSplitPage
component doesn't receive theprojectMeta
prop. If this component contains links or navigation that should be project-scoped, it may need the project context.Please verify if
ContractSplitPage
needs project context for any internal navigation or links:
🏁 Script executed:
#!/bin/bash # Description: Check if ContractSplitPage component uses any navigation or links that might benefit from project context # Search for navigation-related patterns in ContractSplitPage ast-grep --pattern 'export $_ ContractSplitPage($_) { $$$ }' # Also search for Link components or router usage rg -A 10 -B 5 "Link|router|href" apps/dashboard/src/app/\(app\)/\(dashboard\)/\(chain\)/\[chain_id\]/\[contractAddress\]/split/ContractSplitPage.tsx || echo "ContractSplitPage.tsx not found at expected location" # Search for any file with ContractSplitPage fd ContractSplitPage.tsxLength of output: 455
🏁 Script executed:
#!/bin/bash # Locate ContractSplitPage.tsx and inspect for navigation-related code FILE=$(fd ContractSplitPage.tsx | head -n1) echo "Inspecting file: $FILE" echo "- Checking for Link imports" rg -n "import.*Link" "$FILE" || echo "No Link imports found" echo "- Checking for next/link imports" rg -n "import.*next/link" "$FILE" || echo "No next/link imports found" echo "- Checking for href attributes" rg -n "href=" "$FILE" || echo "No href attributes found" echo "- Checking for router usage" rg -n "router\." "$FILE" || echo "No router usage found"Length of output: 1429
Ignore passing
projectMeta
to ContractSplitPage
No link, router or navigation logic exists inContractSplitPage.tsx
, so there’s currently no need for a project context prop.Likely an incorrect or invalid review comment.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/ContractEditModulesPage.client.tsx (2)
13-13
: Well-implemented prop addition.The optional
projectMeta
prop is properly typed and aligns with the component's dual usage in both project-scoped and legacy routing contexts.
26-31
: Correct implementation of project-aware redirect.The
projectMeta
prop is properly passed toRedirectToContractOverview
, enabling project-scoped URL generation when redirecting non-modular core contracts. The conditional logic flow remains intact while adding the necessary project context.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/ContractDirectListingsPage.client.tsx (2)
4-4
: Consistent implementation with project metadata support.The import and prop addition follow the same pattern as other components in this refactor, maintaining consistency across the codebase. The optional
projectMeta
typing is appropriate for dual-context usage.Also applies to: 13-13
26-31
: Proper project-aware redirect for unsupported direct listings.The redirect logic correctly passes
projectMeta
to enable project-scoped URL generation when direct listings are not supported. The conditional check usingisDirectListingSupported
is appropriate for this marketplace component.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/page.tsx (2)
1-1
: Excellent page simplification through shared component delegation.The refactoring to use
SharedContractSplitPage
effectively centralizes complex contract handling logic while simplifying the page component. This approach reduces code duplication and improves maintainability across the contract dashboard.Also applies to: 11-17
15-15
: Appropriate explicitprojectMeta
handling for legacy route.Setting
projectMeta: undefined
is correct for this legacy route context, clearly indicating that this page operates without project scope. This explicit handling helps maintain clarity between legacy and project-scoped routing paths.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/page.tsx (1)
1-1
: Consistent page simplification following established pattern.The refactoring matches the pattern established in other contract pages, delegating complex logic to
SharedContractAccountPermissionsPage
while maintaining appropriate parameter mapping and explicitprojectMeta: undefined
for the legacy route context.Also applies to: 10-18
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/ContractProposalsPage.client.tsx (3)
4-4
: LGTM: Import path is correct for ProjectMeta type.The relative import path correctly references the ProjectMeta type definition from the team/project contract types.
13-13
: LGTM: Optional projectMeta prop follows the established pattern.The addition of the optional
projectMeta
prop is consistent with the broader refactoring effort to support project-scoped routing throughout the dashboard.
26-31
: LGTM: Proper propagation of projectMeta to child component.The
projectMeta
prop is correctly passed to theRedirectToContractOverview
component, ensuring consistent project context for URL construction and navigation.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/BuildYourApp.tsx (3)
4-4
: LGTM: Import path is correct for ProjectMeta type.The relative import path correctly references the ProjectMeta type definition.
10-14
: LGTM: Clean implementation of project-scoped URL construction.The conditional logic properly constructs the
contractRootPath
whenprojectMeta
is available, enabling project-scoped URLs while maintaining backward compatibility.
26-26
: LGTM: Proper usage of contractRootPath in href construction.The
contractRootPath
is correctly prepended to the URL, enabling proper navigation within the team/project context when available.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/contract-page-layout.tsx (3)
9-9
: LGTM: Import path is correct for ProjectMeta type.The relative import path correctly references the ProjectMeta type definition.
20-20
: LGTM: Clean addition of projectMeta prop.The
projectMeta
prop is properly added to the component interface and destructured, following the established pattern for project-scoped routing support.Also applies to: 35-35
50-50
: LGTM: Improved prop passing to PrimaryDashboardButton.The changes correctly:
- Add
projectMeta
prop for project context- Use
contract.client
instead of a separate client prop, which is cleaner and more consistentAlso applies to: 59-59
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/TokenIdPage.client.tsx (3)
4-4
: LGTM: Import path is correct for ProjectMeta type.The relative import path correctly references the ProjectMeta type definition from the team/project contract types.
15-15
: LGTM: Optional projectMeta prop follows the established pattern.The addition of the optional
projectMeta
prop is consistent with the broader refactoring effort to support project-scoped routing throughout the dashboard.
31-36
: LGTM: Proper propagation of projectMeta to child components.The
projectMeta
prop is correctly passed to both:
RedirectToContractOverview
for proper URL construction during redirectsTokenIdPage
for consistent project context throughout the component treeAlso applies to: 46-46
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/page.tsx (1)
1-19
: LGTM! Clean refactor to shared component pattern.The refactor successfully extracts complex contract fetching and validation logic to
SharedModulesPage
, making this page component much simpler and more maintainable. The parameter mapping fromchain_id
tochainIdOrSlug
is consistent with the shared component's interface.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/contract-page-layout.client.tsx (3)
5-7
: Clean type import updates for project-scoped routing.The import changes correctly replace the
ThirdwebClient
dependency withProjectMeta
to support team/project-scoped navigation.
19-19
: Props updated to support project metadata.The prop change from
client: ThirdwebClient
toprojectMeta: ProjectMeta | undefined
aligns with the project-scoped routing refactor across the dashboard.
43-43
: Correct integration with sidebar link generation.Passing
projectMeta
togetContractPageSidebarLinks
ensures that sidebar navigation URLs are properly prefixed with team/project context when available.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/events/shared-events-page.tsx (1)
1-31
: Well-implemented shared component following established patterns.The
SharedEventsPage
component correctly implements the shared component pattern with proper error handling and parameter structure. It usesprojectMeta
parameter (consistent withSharedModulesPage
), handles the not-found case appropriately, and passes the necessary props toEventsFeed
.The component properly extracts
teamId
fromprojectMeta
when callinggetContractPageParamsInfo
, ensuring team-scoped contract resolution works correctly.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/proposals/page.tsx (1)
1-29
: LGTM! Clean implementation following the established pattern.This page component correctly implements the team/project-scoped contract proposals functionality by:
- Properly awaiting the params Promise (consistent with Next.js server components)
- Fetching team data and handling not found cases appropriately
- Constructing the projectMeta object with the correct team and project information
- Delegating rendering to the shared component
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/AccountPage.client.tsx (1)
5-5
: LGTM! Proper prop threading for project-scoped functionality.The changes correctly implement support for the optional
projectMeta
prop by:
- Adding the appropriate import for the
ProjectMeta
type- Including the prop in the component interface as optional
- Passing it through to both
RedirectToContractOverview
andAccountPage
componentsThis follows the consistent pattern established across other similar client components in the dashboard.
Also applies to: 15-15, 28-33, 42-42
apps/dashboard/src/app/(app)/account/contracts/_components/DeployedContractsPage.tsx (1)
15-16
: LGTM! Clean prop threading for team/project context.The addition of
teamSlug
andprojectSlug
props is implemented correctly:
- Props are consistently added to both the main and async component interfaces
- They are properly passed through to the
ContractTable
component- No breaking changes introduced
This enables the component to work within the team/project-scoped routing structure.
Also applies to: 44-45, 63-64
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/page.tsx (1)
1-19
: LGTM! Clean refactoring following separation of concerns.This refactoring successfully delegates all contract-specific logic to the
SharedNFTPage
component, simplifying the page component to focus only on parameter extraction. The pattern of passingprojectMeta: undefined
is consistent with the dashboard routes not having project context yet, while the shared component can handle both scenarios.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/ContractEnglishAuctionsPage.client.tsx (2)
10-14
: LGTM! Proper addition of projectMeta prop.The
projectMeta
prop is correctly typed as optional and follows the established pattern for enabling project-scoped routing.
26-31
: LGTM! Correct prop forwarding for project-scoped redirects.The
RedirectToContractOverview
component now receives theprojectMeta
prop, enabling it to redirect to the appropriate project-scoped URL when applicable.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/code/page.tsx (1)
1-19
: LGTM! Consistent refactoring pattern.This change follows the same clean refactoring pattern as other contract pages, successfully delegating complex logic to the
SharedCodePage
component while maintaining proper parameter passing. TheprojectMeta: undefined
is appropriate for dashboard routes.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/ContractNFTPage.client.tsx (2)
10-14
: LGTM! Consistent prop addition pattern.The
projectMeta
prop addition follows the established pattern and is properly typed as optional.
28-33
: LGTM! Complete prop forwarding for project-scoped functionality.Both the
RedirectToContractOverview
andContractNFTPage
components now correctly receive theprojectMeta
prop, enabling proper project-scoped routing and UI context throughout the NFT page flow.Also applies to: 36-44
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/contract-overview-page.client.tsx (1)
4-4
: LGTM! Clean implementation of project metadata propagation.The changes properly introduce the
ProjectMeta
prop with correct typing, optional handling, and clean prop threading through the component hierarchy.Also applies to: 12-12, 14-14, 30-30
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/ContractNFTPage.tsx (1)
4-4
: LGTM! Consistent implementation pattern.The changes follow the same clean pattern as other components, properly integrating project metadata into the NFT page with correct typing and prop propagation.
Also applies to: 20-20, 28-28, 113-113
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/AccountsPage.client.tsx (1)
4-4
: LGTM! Proper prop threading to child components.The implementation correctly passes the
projectMeta
to both the redirect and main page components, maintaining consistency with the overall refactoring pattern.Also applies to: 13-13, 26-31, 35-40
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/modules/page.tsx (1)
6-14
: LGTM! Proper async handling and error management.The implementation correctly handles the async params, fetches project data, and uses
notFound()
for missing resources, which is the appropriate 404 handling pattern for Next.js.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/sources/shared-sources-page.tsx (1)
1-19
: Clean shared component implementation following established patterns.This shared server component correctly implements the pattern seen across the PR:
- Proper contract info fetching with error handling
- Clean separation between data fetching and rendering logic
- Consistent parameter structure with optional team context
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/events/page.tsx (1)
6-29
: Good implementation of project-scoped page pattern.The implementation correctly:
- Awaits the params Promise (consistent with Next.js behavior noted in learnings)
- Implements proper error handling for missing projects
- Follows the established pattern for passing projectMeta to shared components
- Maintains consistency with other project-scoped pages in the PR
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/analytics/page.tsx (1)
1-19
: Excellent refactoring to centralize logic in shared components.This simplification successfully:
- Delegates complex contract info fetching and validation to SharedAnalyticsPage
- Maintains the same page interface while reducing duplication
- Correctly passes undefined for projectMeta in non-project context
- Follows the consistent pattern established across other contract pages
This refactor improves maintainability by centralizing the complex analytics logic.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/(marketplace)/direct-listings/page.tsx (1)
6-29
: Consistent implementation with clear variable naming.This project-scoped page correctly:
- Uses appropriate API call (
getTeamBySlug
) for fetching team data- Maintains clear variable naming (
team
for team data)- Implements consistent error handling and parameter passing patterns
- Properly awaits the params Promise as expected in Next.js
The implementation is consistent with the established pattern across other project-scoped pages in this PR.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/page.tsx (1)
1-20
: LGTM! Clean refactoring to shared component pattern.The simplification of this page by delegating logic to
SharedContractTokensPage
is a good architectural improvement. The async/await pattern for params is correct for Next.js server components, and passingundefined
forteamId
is appropriate for the non-team scoped route.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractFromParams.ts (2)
8-12
: LGTM! Parameter updates support team-scoped functionality.The renaming of
chain_id
tochainIdOrSlug
improves consistency, and the addition of the optionalteamId
parameter correctly supports the team-scoped contract functionality.
35-37
: LGTM! Correct usage of updated getUserThirdwebClient API.The function call correctly passes the
teamId
parameter in the expected object format, matching the updatedgetUserThirdwebClient
function signature.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/code/page.tsx (2)
12-14
: LGTM! Proper error handling for missing projects.The
notFound()
call correctly handles cases where the project doesn't exist or the user doesn't have access.
17-27
: LGTM! Correct projectMeta construction and prop passing.The
projectMeta
object is properly constructed with all required fields and correctly passed to theSharedCodePage
component, enabling team/project-scoped functionality.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/AccountPage.tsx (3)
6-6
: LGTM! Correct import of ProjectMeta type.The import path correctly references the ProjectMeta type definition from the team/project contract types.
16-16
: LGTM! Appropriate addition of projectMeta prop.The optional
projectMeta
prop addition enables team/project-scoped functionality while maintaining backward compatibility.
50-54
: LGTM! Correct prop forwarding to NftsOwned component.The
projectMeta
prop is properly passed to theNftsOwned
component, enabling project-scoped NFT functionality as shown in the relevant code snippets.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/ContractPermissionsPage.tsx (2)
8-8
: LGTM: Clean import of ProjectMeta type.The import path correctly references the types file for the project-scoped contract pages.
16-16
: LGTM: Proper projectMeta prop integration.The implementation correctly:
- Adds optional projectMeta prop to the interface
- Constructs contractRootPath conditionally based on projectMeta presence
- Defaults to empty string when projectMeta is undefined
- Uses the path consistently in explorerHref construction
This follows the expected pattern for enabling project-scoped URLs.
Also applies to: 21-30
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/account-permissions/page.tsx (1)
1-1
:✅ Verification successful
Inconsistent data fetching approach compared to similar pages.
This page uses
getTeamBySlug
to fetch team data, but the route structure suggests it should be fetching project-specific data. Compare with the NFTs page which usesgetProject(params.team_slug, params.project_slug)
for the same route pattern.Let me verify the correct API to use for project-scoped pages:
Also applies to: 10-10
🏁 Script executed:
#!/bin/bash # Check which API function is used in other similar project-scoped contract pages rg -A 5 "getTeamBySlug|getProject" apps/dashboard/src/app/\(app\)/team/\[team_slug\]/\[project_slug\]/contract/Length of output: 42668
No change needed for data fetching approach
The account-permissions page aligns with a group of contract subpages (split, tokens, sources, proposals, settings, account, accounts, english-auctions, direct-listings) that intentionally use
getTeamBySlug
. Pages that require project-scoped metadata (events, permissions, NFTs, modules, explorer, cross-chain, code, analytics, claim-conditions) usegetProject
. This split is by design, so no update is required here.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/explorer/page.tsx (1)
1-1
: LGTM: Clean architectural improvement.The simplification to delegate to
SharedExplorerPage
is a good architectural change that centralizes complex contract data fetching and conditional rendering logic. SettingprojectMeta: undefined
is appropriate for the non-project-scoped route.Also applies to: 11-17
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/page.tsx (1)
68-69
: LGTM: Clean propagation of team/project contextThe changes correctly propagate
teamSlug
andprojectSlug
through the component hierarchy to enable team/project-scoped URLs in theContractTable
component. The implementation is clean and follows the established pattern.Also applies to: 97-98, 116-117
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/NFTDetails.tsx (1)
10-10
: LGTM: Correct implementation of conditional URL constructionThe changes properly implement team/project context support by:
- Adding optional
projectMeta
prop with correct typing- Conditionally constructing URLs with team/project prefix when context is available
- Maintaining backward compatibility by falling back to original behavior
- Correctly propagating the context to child components
Also applies to: 18-18, 26-26, 28-32, 68-68
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/[tokenId]/page.tsx (1)
1-34
: LGTM: Follows established pattern correctlyThe page component correctly implements the pattern of:
- Fetching project data using the API
- Handling missing projects with 404 responses
- Delegating rendering to shared components with enriched metadata
- Constructing proper
ProjectMeta
object for team/project contextapps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/PermissionsTable.tsx (1)
22-22
: LGTM: Consistent implementation of project contextThe changes correctly follow the established pattern by:
- Adding optional
projectMeta
prop with proper typing- Conditionally constructing the base path for permissions URLs
- Maintaining backward compatibility when project context is not available
- Using the constructed path consistently in the component
The implementation is consistent with similar changes in other overview components.
Also applies to: 28-28, 30-32, 62-62
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/settings/page.tsx (1)
1-25
: LGTM! Clean implementation following the new pattern.The implementation correctly follows the bridge pattern for team/project scoped routing:
- Properly awaits params (following Next.js best practices)
- Fetches team data with appropriate error handling
- Delegates to shared component with correct projectMeta construction
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/account/page.tsx (1)
1-29
: LGTM! Consistent implementation following the established pattern.This implementation is consistent with the settings page and correctly follows the bridge pattern for team/project scoped routing.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/AccountsPage.tsx (1)
6-6
: LGTM! Clean addition of projectMeta support.The changes correctly add
projectMeta
prop support to enable team/project scoped routing. The implementation is minimal, well-typed, and follows the established pattern.Also applies to: 14-14, 20-20, 49-49
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/page.tsx (1)
6-10
: Good call on awaitingprops.params
This matches the quirky Next.js behaviour we learnt previously (params occasionally arrive as a
Promise
).
No action needed.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/page.tsx (1)
4-8
: Double-check whetherparams
really needs to be awaited on this routeUnlike the
team/...
routes, this file hasn’t introduced a custom segment that triggers the params-as-Promise quirk.
Awaiting an object that’s already synchronous is harmless, but it does hide potential type mismatches and can confuse future maintainers.Please verify with:
export default function Page({ params }: { params: { /* … */ } }) {If it compiles, prefer the synchronous version; otherwise keep the
await
and add a short comment explaining the rationale.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/cross-chain/page.tsx (1)
1-29
: LGTM! Clean implementation of the project-scoped contract page pattern.The implementation correctly follows the established pattern:
- Properly extracts and awaits route parameters
- Fetches project data with appropriate error handling via
notFound()
- Delegates rendering to the shared component with well-structured
projectMeta
- Maintains type safety with
ProjectContractPageParams
The long relative import path for
SharedCrossChainPage
is consistent with the established file structure, though it could benefit from path mapping in the future.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/connect/account-abstraction/factories/page.tsx (1)
53-54
: Good prop propagation for project-scoped routing.The addition of
teamSlug
andprojectSlug
props follows a clean pattern:
- Props are consistently extracted from the fetched team/project objects
- Proper threading through the component hierarchy to
FactoryContracts
- Maintains backward compatibility while enabling project-scoped URL construction
This aligns well with the broader refactor to support team/project context in contract-related pages.
Also applies to: 65-66, 105-106, 117-118, 151-152
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/page.tsx (1)
1-19
: Excellent refactor to shared component pattern.The simplification effectively centralizes complex logic in
SharedAccountsPage
while maintaining the same functionality:
- Proper delegation to the shared component with correct parameter mapping
projectMeta: undefined
appropriately indicates this is a non-project-scoped route- Parameter rename from
chain_id
tochainIdOrSlug
improves consistency across the codebaseThe shared component handles all the previously embedded logic including contract fetching, account validation, and conditional rendering based on chain type and contract capabilities.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/page.tsx (1)
1-19
: Consistent implementation of the shared component pattern.This refactor follows the same excellent pattern as the accounts page:
- Clean delegation to
SharedDirectListingsPage
with proper parameter mapping- Correct use of
projectMeta: undefined
for non-project-scoped routes- Consistent parameter naming with
chainIdOrSlug
The shared component encapsulates all the complex logic including account fetching, contract validation, marketplace capability checks, and conditional rendering that was previously embedded in this page.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/claim-conditions/page.tsx (1)
6-29
: LGTM! Well-structured server component implementation.The page follows a clean pattern of parameter resolution, data fetching, error handling, and delegation to a shared component. The async/await handling and 404 error responses are implemented correctly.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/Analytics.tsx (1)
25-38
: LGTM! Clean implementation of project-scoped URL generation.The conditional
contractRootPath
logic correctly builds team/project-prefixed URLs whenprojectMeta
is available, enabling proper navigation within project contexts.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/events/page.tsx (1)
10-18
: LGTM! Excellent refactoring that centralizes logic.The simplified implementation that delegates contract data fetching and validation to
SharedEventsPage
is a good architectural decision. SettingprojectMeta: undefined
is correct for this non-project context.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/explorer/page.tsx (1)
6-29
: LGTM! Consistent implementation following established patterns.The page correctly implements the pattern established across other contract pages: parameter resolution, project data fetching, error handling, and delegation to shared components. The async/await handling is proper per Next.js server component requirements.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/page.tsx (2)
3-9
: Remove unnecessary Promise wrapper aroundparams
params
is synchronously injected by Next.js and is not aPromise
.
Typing it asPromise<…>
and awaiting it:
- introduces an avoidable
async
render path,- forces the whole component to be
async
,- makes the call-site contract inaccurate (Next.js will pass an object, not a promise).
A small refactor simplifies the file and removes the superfluous
await
.-export default async function Page(props: { - params: Promise<{ - contractAddress: string; - chain_id: string; - }>; -}) { - const params = await props.params; +export default function Page(props: { + params: { + contractAddress: string; + chain_id: string; + }; +}) { + const { params } = props;If you still need the function to be
async
for other reasons (e.g. headers, cookies) you can keepasync
while dropping thePromise
type.
[ suggest_essential_refactor ]
14-16
: Consider normalising thechain_id
keyInternally you map
chain_id → chainIdOrSlug
.
If possible, expose the canonical name (chainIdOrSlug
) at the route level to avoid this translation step and reduce chances of a typo drifting between files.
If changing the route segment is not feasible, at least add a comment here explaining the mismatch for future readers.
[ suggest_nitpick ]apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/page.tsx (2)
3-9
: Sameparams
Promise issue as aboveThe
NFT
token page repeats the Promise pattern.
Please apply the same refactor as suggested for the overview page to keep the codebase consistent and accurate.
[ duplicate_comment ]
14-18
: Guard against missingprojectMeta
to avoid prop churnYou explicitly pass
projectMeta: undefined
.
Because the property is already optional in the shared component, omitting it entirely keeps the call-site cleaner and prevents ESLint/TS from propagating “possibly undefined” checks downstream.- tokenId: params.tokenId, - projectMeta: undefined, + tokenId: params.tokenId,[ suggest_nitpick ]
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/NFTCards.tsx (4)
6-6
: Brittle deep-relative import forProjectMeta
The import path climbs six directories and reaches into a route-specific folder:
import type { ProjectMeta } from "../../../../../team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types";This is highly fragile:
- a single folder rename will break every consumer,
- it creates an accidental dependency on a page-layer file from a shared component, risking circular builds.
Move
ProjectMeta
to a centraltypes
(e.g.@/types/project
) and reference it via a path alias to improve stability.-import type { ProjectMeta } from "../../../../../team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types"; +import type { ProjectMeta } from "@/types/project";[ suggest_essential_refactor ]
33-34
: Prop should be optionalThe prop is declared as
projectMeta: ProjectMeta | undefined;
but not marked optional (?
).
Marking it optional improves DX and matches usage patterns.-interface NFTCardsProps { +interface NFTCardsProps { ... - projectMeta: ProjectMeta | undefined; + projectMeta?: ProjectMeta; }[ suggest_nitpick ]
49-52
: Avoid manual string concatenation for routesBuilding URLs with template literals is error-prone and duplicates knowledge of routing rules.
Consider a helper:import { buildContractPath } from "@/lib/paths"; ... const href = buildContractPath({ projectMeta, chainId: token.chainId, contractAddress: token.contractAddress, slug: `nfts/${tokenId}`, });Centralising route logic prevents drift when path patterns evolve (e.g., moving from
/team
to/t
).
[ suggest_optional_refactor ]
95-98
: Missing leading slash whenprojectMeta
is defined
contractRootPath
already starts with a/
.
WhenprojectMeta
is not defined, the final URL correctly starts with/
.
WhenprojectMeta
is defined, the concatenation yields
/team/.../contract/<chain>/<address>/nfts/<id>
— ✅
Just sanity-checked: there is no double slash, so nothing breaks here.
[ approve_code_changes ]apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/accounts/page.tsx (1)
1-29
: LGTM! Clean implementation following established patterns.This page component follows the established pattern for team/project-scoped contract pages:
- Proper async/await usage with Next.js App Router
- Appropriate error handling with
notFound()
for missing teams- Clean delegation to shared component logic
- Correctly constructed
projectMeta
object matching theProjectMeta
typeThe implementation is consistent with other similar pages in the codebase.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/LatestEvents.tsx (2)
31-43
: LGTM! Clean conditional URL construction.The implementation correctly:
- Maintains backward compatibility with
undefined
projectMeta- Constructs project-scoped URLs when projectMeta is available
- Uses the constructed path to build the events link
This follows the established pattern for project-aware routing.
25-25
:✅ Verification successful
Verify import path consistency.
The import uses a relative path with many directory traversals. Consider whether this could be simplified with a path alias or if it matches the pattern used in other similar imports across the codebase.
🏁 Script executed:
#!/bin/bash # Check if there's a consistent pattern for ProjectMeta imports across the codebase rg -A 2 -B 2 "import.*ProjectMeta" --type tsx --type tsLength of output: 85
To verify consistency of
ProjectMeta
imports and check for any path aliases:
🏁 Script executed:
#!/bin/bash # 1. Find all imports of ProjectMeta in .ts/.tsx files rg "import.*ProjectMeta" --glob "*.ts" --glob "*.tsx" -nLength of output: 14250
🏁 Script executed:
#!/bin/bash # 2. Inspect tsconfig.json for configured path aliases grep -R '"paths"' -n tsconfig.json && sed -n '/"paths"\s*:/,/\]/p' tsconfig.jsonLength of output: 83
Import path consistency confirmed
All
ProjectMeta
imports in the dashboard use the same deep-relative path pattern and there’s no path alias configuration in the repo (notsconfig.json
definingpaths
was found). This matches other components—no changes needed.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/components/ContractChecklist.tsx (3)
24-59
: LGTM! Comprehensive URL construction with proper dependencies.The implementation correctly:
- Adds projectMeta to component props interface
- Constructs conditional URL paths for all navigation links
- Maintains backward compatibility when projectMeta is undefined
- Uses the constructed paths consistently throughout the component
The approach is thorough and follows the established pattern.
347-367
: Excellent dependency management in useMemo.Good practice including all the href variables in the useMemo dependency array. This ensures the steps are recalculated when the URL paths change based on project context.
15-15
:✅ Verification successful
Verify import path consistency.
Similar to the previous file, this uses a deeply nested relative import path. Ensure this pattern is consistent across the codebase.
🏁 Script executed:
#!/bin/bash # Check for consistent ProjectMeta import patterns rg "import.*ProjectMeta.*from.*team.*project_slug.*types" --type tsx --type tsLength of output: 108
🏁 Script executed:
#!/bin/bash # Search for all ProjectMeta imports across TS and TSX files without type filters rg "import.*ProjectMeta.*from" -g "*.ts" -g "*.tsx"Length of output: 14117
Import path consistency verified.
The
ProjectMeta
import uses the appropriate number of../
across all files relative to their directory depth, matching the pattern in other components. No changes needed.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/shared-permissions-page.tsx (1)
1-54
: LGTM! Well-structured shared component with excellent async patterns.This implementation demonstrates several best practices:
- Efficient data fetching: Uses
Promise.all
to concurrently fetch contract info and auth token- Proper error handling: Returns
notFound()
when contract info is missing- Clean separation of concerns: Delegates to appropriate components based on chain type
- Type safety: Properly typed parameters including optional
projectMeta
- Consistent patterns: Follows the established pattern for shared contract page components
The component successfully centralizes the async logic while maintaining flexibility for different rendering contexts.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/redirect-contract-overview.client.tsx (3)
6-6
: LGTM: Proper type import for ProjectMetaThe import correctly references the ProjectMeta type from the team/project types file.
10-11
: LGTM: Interface updated to include projectMetaThe addition of the optional
projectMeta
prop with correct typing aligns with the broader refactor pattern across the dashboard.
22-30
: LGTM: Conditional URL construction logic is correctThe conditional logic properly handles both scenarios:
- Without projectMeta: uses legacy URL format
/{chainId}/{contractAddress}
- With projectMeta: uses project-scoped format
/team/{teamSlug}/{projectSlug}/contract/{chainId}/{contractAddress}
The destructuring of
teamSlug
andprojectSlug
is safe since the conditional check ensuresprojectMeta
is defined.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/permissions/page.tsx (2)
1-1
: LGTM: Proper delegation to shared componentThe import of
SharedPermissionsPage
follows the established pattern for this refactor.
11-17
: LGTM: Clean parameter mapping and delegationThe page component is correctly simplified to delegate all logic to
SharedPermissionsPage
. Key improvements:
- Parameter mapping:
chain_id
→chainIdOrSlug
aligns with the shared component's interface- Explicit projectMeta: Setting to
undefined
clearly indicates this is a non-project route- Logic delegation: Complex contract fetching, validation, and conditional rendering is now handled by the shared component
This pattern improves maintainability and consistency across the codebase.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/[tokenId]/token-id.tsx (5)
31-31
: LGTM: Correct type importThe import properly references the ProjectMeta type from the team/project types file.
57-57
: LGTM: Interface updated with projectMetaThe addition of the optional
projectMeta
prop maintains backward compatibility while enabling project-scoped functionality.
68-68
: LGTM: Component parameter updatedThe component correctly accepts the new
projectMeta
parameter for use in path construction.
74-76
: LGTM: Conditional path constructionThe
contractRootPath
logic correctly handles both scenarios:
- With projectMeta: constructs
/team/{teamSlug}/{projectSlug}/contract
prefix- Without projectMeta: uses empty string (maintains existing behavior)
This pattern aligns with the broader refactor across the dashboard.
139-144
: LGTM: Breadcrumb navigation updated consistentlyThe breadcrumb link correctly uses the
contractRootPath
for both thehref
and therouter.push
call, ensuring consistent navigation behavior in project-scoped and legacy contexts.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/page.tsx (2)
1-1
: LGTM: Consistent delegation patternThe import of
SharedContractAccountPage
follows the established refactor pattern across the dashboard.
11-17
: LGTM: Effective simplification with proper delegationThe page component successfully delegates all complex logic to
SharedContractAccountPage
. This refactor provides several benefits:
- Consistency: Follows the same pattern as other contract pages (permissions, direct-listings, etc.)
- Maintainability: Complex logic is centralized in the shared component
- Clear intent: Explicit
projectMeta: undefined
indicates non-project context- Parameter mapping:
chain_id
→chainIdOrSlug
aligns with shared component interfaceThe previous complex logic for contract info fetching, localhost handling, and conditional rendering is now properly encapsulated in the shared component.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/shared-nfts-page.tsx (2)
17-25
: Good use of parallel data fetching.The parallel fetching of contract info and account data using
Promise.all
is an efficient approach that reduces the overall loading time.
45-51
: Proper validation and redirect handling.The ERC standard validation and redirect to the contract landing page for unsupported contracts follows good defensive programming practices.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageSidebarLinks.ts (1)
15-17
: Clean implementation of project-scoped URL construction.The conditional
layoutPrefix
construction properly handles both project-scoped and legacy URL patterns, maintaining backward compatibility while enabling the new functionality.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/page.tsx (1)
11-17
: Excellent refactoring to shared component pattern.The simplification of this page component by delegating to
SharedEnglishAuctionsPage
reduces code duplication and centralizes the contract page logic. The parameter mapping and explicitprojectMeta: undefined
are appropriate for this non-project-scoped route.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx (2)
53-55
: Consistent implementation of project-scoped URL construction.The
contractRootPath
construction follows the same pattern established in the sidebar links utility, ensuring consistent URL handling across the dashboard.
67-67
: Proper integration of project-scoped path in code snippets link.The code snippets button correctly uses the constructed
contractRootPath
to maintain URL consistency within project contexts.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/cross-chain/data-table.tsx (4)
61-61
: LGTM: Correct import of ProjectMeta type.The import path correctly references the ProjectMeta type definition from the team/project contract types.
95-95
: LGTM: Proper prop interface integration.The
projectMeta
prop is correctly added as optional to both the function signature and props interface, maintaining backward compatibility.Also applies to: 105-105
246-250
: LGTM: Correct conditional URL construction for network links.The URL construction properly handles both project-scoped and non-project-scoped routing by conditionally prefixing with team and project slugs when
projectMeta
is available.
417-421
: LGTM: Consistent URL construction for deploy status modal.The view contract link construction follows the same conditional pattern as the network links, ensuring consistent navigation behavior throughout the component.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/overview/ContractOverviewPage.tsx (3)
2-2
: LGTM: Correct import of ProjectMeta type.The import correctly references the ProjectMeta type definition for use in the component props.
24-24
: LGTM: Proper prop interface and component integration.The
projectMeta
prop is correctly added as optional to the interface and component props, maintaining consistency with other components in the refactor.Also applies to: 41-41
53-53
: LGTM: Consistent prop propagation to child components.All relevant child components (
ContractChecklist
,ContractAnalyticsOverviewCard
,MarketplaceDetails
,NFTDetails
,LatestEvents
,PermissionsTable
, andBuildYourApp
) properly receive theprojectMeta
prop, enabling project-scoped behavior throughout the component tree.Also applies to: 62-62, 69-69, 83-83, 93-93, 101-101, 109-109
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/table.tsx (2)
44-44
: LGTM: Correct import of ProjectMeta type.The import correctly references the ProjectMeta type definition with proper relative path resolution.
50-50
: LGTM: Proper prop interface integration.The
projectMeta
prop is correctly added as optional to both the interface and component props.Also applies to: 56-56
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/code/shared-code-page.tsx (5)
1-7
: LGTM: Proper imports and dependencies.All necessary imports are correctly included, including the ProjectMeta type, utility functions, and components needed for the server component.
8-14
: LGTM: Well-structured component interface.The props interface is properly typed with clear parameter structure including the optional
projectMeta
for team/project context.
16-24
: LGTM: Proper data fetching and error handling.The component correctly calls
getContractPageParamsInfo
with the teamId from projectMeta and properly handles the 404 case when no contract information is found.
29-36
: LGTM: Appropriate conditional rendering for localhost chains.The component correctly handles localhost chains by rendering the client-side component, which is necessary for chains that may not have server-side contract resolution capabilities.
38-46
: LGTM: Robust ABI resolution with error handling.The ABI resolution includes proper error handling with
.catch(() => undefined)
, ensuring the component doesn't crash if ABI resolution fails, and gracefully passes undefined to the server component.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/explorer/shared-explorer-page.tsx (1)
9-53
: Well-structured shared component with good performance patterns.This component effectively centralizes the explorer page logic with several good practices:
- Parallel data fetching using
Promise.all
for optimal performance- Graceful error handling for ABI resolution failures
- Clean conditional rendering based on chain type
- Proper 404 handling for missing contract information
The architecture promotes code reuse while maintaining type safety with the optional
ProjectMeta
parameter.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/settings/shared-settings-page.tsx (1)
10-56
: Excellent implementation with robust fee configuration handling.The component demonstrates several best practices:
- Efficient parallel data fetching with
Promise.all
- Robust platform fee checking with proper error handling (lines 42-46)
- Correct case-insensitive address comparison for fee recipient validation
- Consistent error handling pattern with
notFound()
for missing contract infoThe fee configuration logic gracefully handles contracts that don't support platform fees by catching exceptions and defaulting to
true
.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/shared-direct-listings-page.tsx (1)
9-54
: Consistent implementation following established patterns.This component maintains the architectural consistency seen across other shared pages:
- Efficient parallel data fetching for account and contract information
- Proper feature validation (direct listing support) before rendering
- Correct error handling with
notFound()
for unsupported features- Clean separation between localhost and production chain handling
The
projectMeta
propagation to client components enables proper project-scoped routing.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/english-auctions/shared-english-auctions-page.tsx (1)
29-53
: Clean feature validation and rendering logic.The remaining implementation is excellent:
- Proper feature support validation for English auctions
- Consistent error handling with
notFound()
for unsupported features- Correct prop propagation including
projectMeta
for project-scoped routing- Clean separation between client and server rendering paths
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/proposals/shared-proposals-page.tsx (3)
1-15
: LGTM! Clean component structure and imports.The component follows the consistent pattern established for shared contract components, with proper imports and TypeScript typing.
16-28
: Correct contract info fetching and error handling.The component properly fetches contract information using the team context and handles the 404 case appropriately.
29-37
: Localhost rendering implemented correctly.The client component receives all necessary props including projectMeta for proper navigation handling.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/shared-split-page.tsx (1)
1-27
: Well-structured shared component following established pattern.The component correctly implements the contract info fetching, error handling, and conditional rendering logic consistent with other shared contract components.
Also applies to: 30-45
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/shared-accounts-page.tsx (2)
29-34
: Excellent use of concurrent fetching for performance.The Promise.all implementation with conditional metadata fetching for non-localhost chains is a good performance optimization.
50-56
: Good consistency in projectMeta prop passing.Unlike some other shared components, this correctly passes
projectMeta
to both client and server components for consistent behavior.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account/shared-account-page.tsx (1)
1-59
: Excellent implementation following best practices.This shared component demonstrates the most consistent implementation of the established pattern:
- Proper variable naming (
account
instead of variations)- Consistent
projectMeta
passing to both client and server components- Includes
chainMetadata
where needed- Clean error handling and conditional rendering
This serves as a good reference for the other shared components.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/shared-page.tsx (1)
1-50
: LGTM! Well-structured shared component with proper error handling.This shared component follows an excellent pattern by centralizing contract token page logic with proper error handling and conditional rendering. The implementation correctly:
- Fetches contract information with appropriate error handling
- Separates localhost and remote chain rendering paths
- Uses ERC20 feature detection via function selectors
- Passes the correct props to child components
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/account-permissions/shared-account-permissions-page.tsx (1)
37-44
: Good feature validation with appropriate error handling.The component properly validates that the contract supports account permissions before rendering, and returns a 404 if not supported. This provides a better user experience than showing an error page.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/cross-chain/page.tsx (1)
11-17
: Clean refactor that delegates logic to shared component.This simplification effectively moves complex cross-chain logic into the shared component while maintaining the same functionality. Setting
projectMeta: undefined
is appropriate for non-project-scoped routes.apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/shared-modules-page.tsx (1)
42-50
: Good feature validation with proper redirect handling.The component correctly validates modular core support and redirects to the contract landing page when not supported, properly passing through the project metadata for consistent navigation.
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/layout.tsx (2)
28-30
: Missingaccount
null-check before render
getValidAccount
might returnundefined
, yetaccount
is passed to
<TeamHeaderLoggedIn>
which expects a valid object.
Add a guard to avoid runtime crashes:if (!account) { redirect("/login"); }
16-22
:⚠️ Potential issue
params
should not be declared as aPromise
Next.js injects
params
synchronously (Record<string,string>
).
Typing it asPromise<...>
forces you toawait
something that is not a thenable,
silently widening the type and hiding real compiler errors.-export default async function ContractLayout(props: { - children: React.ReactNode; - params: Promise<ProjectContractPageParams>; -}) { - const params = await props.params; +export default async function ContractLayout(props: { + children: React.ReactNode; + params: ProjectContractPageParams; +}) { + const params = props.params;⛔ Skipped due to learnings
Learnt from: jnsdls PR: thirdweb-dev/js#6929 File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19 Timestamp: 2025-05-21T05:17:31.283Z Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/shared-layout.tsx (1)
131-159
: 🛠️ Refactor suggestionParallelise inner
getProjects
calls to avoid N×M latency
Promise.all
already gathers the outer promises concurrently, but each async mapper awaitsgetProjects
inside the callback, forcing thegetProjects
calls to execute sequentially (one per team).
You can shave seconds off the dashboard load time for users that belong to many teams by starting all project-fetch requests at once:- const teamsAndProjects: MinimalTeamsAndProjects = await Promise.all( - teams.map(async (team) => ({ - team: { - id: team.id, - name: team.name, - slug: team.slug, - image: team.image, - }, - projects: (await getProjects(team.slug)).map((x) => ({ - id: x.id, - name: x.name, - image: x.image, - })), - })), - ); + const teamsAndProjects: MinimalTeamsAndProjects = await Promise.all( + teams.map(async (team) => { + const projects = await getProjects(team.slug); // kick off in parallel + return { + team: { + id: team.id, + name: team.name, + slug: team.slug, + image: team.image, + }, + projects: projects.map((p) => ({ + id: p.id, + name: p.name, + image: p.image, + })), + }; + }), + );(The key change is removing the immediate
await
insidemap
.)
For large organisations this reduces total wait time to the slowest single request instead of the sum of all requests.Likely an incorrect or invalid review comment.
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/cross-chain/shared-cross-chain-page.tsx (1)
28-34
: Confirm props signature aligns with Next.js routing
projectMeta
is injected intoparams
, butparams
normally only contains
path segments provided by the framework.
Ensure every page that calls<SharedCrossChainPage>
manually passes
projectMeta
inside theparams
object; otherwise this will always beundefined
,
breaking team/project scoping.If this was meant to be a separate prop, consider:
export async function SharedCrossChainPage({ params, projectMeta, }: { params: { contractAddress: string; chainIdOrSlug: string }; projectMeta?: ProjectMeta; }) { … }
@@ -1,6 +1,7 @@ | |||
"use client"; | |||
|
|||
import type { ThirdwebContract } from "thirdweb"; | |||
import type { ProjectMeta } from "../../../../../team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types"; |
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.
🛠️ Refactor suggestion
Consider using an absolute import path for better maintainability.
This is the fourth occurrence of the same deep relative import path in this PR. This pattern creates maintenance overhead and tight coupling between components.
Consider creating a centralized approach for this type:
-import type { ProjectMeta } from "../../../../../team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types";
+import type { ProjectMeta } from "@/types/project-meta";
This would eliminate the fragile relative paths across all affected files.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/split/ContractSplitPage.client.tsx
at line 4, replace the deep relative import path for ProjectMeta with an
absolute import path. To fix this, configure a centralized alias or path mapping
in your tsconfig or module resolver that points to the directory containing the
types, then update the import statement to use this alias. This will improve
maintainability by avoiding fragile relative paths repeated across multiple
files.
params: Promise<ProjectContractPageParams>; | ||
}) { | ||
const params = await props.params; | ||
const team = await getProject(params.team_slug, params.project_slug); |
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.
🛠️ Refactor suggestion
Clarify variable naming and data structure.
The variable is named team
but the function call is getProject()
. This naming inconsistency could cause confusion.
Either rename the variable to reflect that it's project data:
- const team = await getProject(params.team_slug, params.project_slug);
+ const project = await getProject(params.team_slug, params.project_slug);
Or verify that the getProject
function actually returns team data (in which case the function name might be misleading).
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/analytics/page.tsx
at line 10, the variable named 'team' is assigned the result of 'getProject()',
causing confusion due to inconsistent naming. Rename the variable to something
like 'project' to accurately reflect the data returned by 'getProject()', or if
the function actually returns team data, rename the function to better represent
its return value. Ensure variable and function names clearly correspond to the
data they handle.
projectSlug: params.project_slug, | ||
teamId: team.id, | ||
teamSlug: team.slug, | ||
}, |
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
Verify the projectMeta construction is correct.
If the fetched data is a project object, ensure that accessing team.id
and team.slug
provides the correct team information for the projectMeta.
Please verify that the project object contains the team ID and slug fields, or if we need to access nested team properties:
🏁 Script executed:
#!/bin/bash
# Search for the Project type definition to understand its structure
ast-grep --pattern 'type Project = {
$$$
}'
# Also search for interface definitions
ast-grep --pattern 'interface Project {
$$$
}'
Length of output: 98
🏁 Script executed:
#!/bin/bash
# Search for projectMeta construction and related variables in analytics page
rg -n "projectMeta" -n "projectSlug" -n "teamId" -n "teamSlug" -n "projectQuery" -n "team =" apps/dashboard/src/app
Length of output: 39563
🏁 Script executed:
#!/bin/bash
# Display first 200 lines of analytics page to inspect projectQuery and team usage
sed -n '1,200p' "apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/analytics/page.tsx"
# Display utils.ts to inspect ProjectMeta type
sed -n '1,200p' "apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/utils.ts"
Length of output: 1671
🏁 Script executed:
#!/bin/bash
# Locate the getProject implementation to inspect its return type
rg -n "export async function getProject" -g "*.ts" -g "*.tsx"
# If not found, search for any definition of getProject
rg -n "function getProject" -g "*.ts" -g "*.tsx" -C3
Length of output: 2656
🏁 Script executed:
#!/bin/bash
# Show imports and type alias in projects API file
sed -n '1,50p' apps/dashboard/src/@/api/projects.ts
# Find definition of ProjectResponse across the codebase
rg -n "type ProjectResponse" -g "*.ts" -g "*.tsx" -C3 || rg -n "interface ProjectResponse" -g "*.ts" -g "*.tsx" -C3
# If ProjectResponse is imported, display its import path
rg -n "ProjectResponse" -g "apps/dashboard/src/@/api/projects.ts"
Length of output: 1943
🏁 Script executed:
#!/bin/bash
# Display the ProjectResponse type with surrounding context to verify available fields
rg -n 'export type ProjectResponse' -C10 packages/service-utils/src/core/api.ts
Length of output: 658
Fix projectMeta construction
The getProject
call returns a ProjectResponse
(alias Project
) with:
id
→ the project’s IDteamId
→ the team’s IDslug
→ the project’s slug
Currently you’re doing:
projectMeta: {
projectSlug: params.project_slug,
teamId: team.id, // ← this is the project ID, not the team ID
teamSlug: team.slug, // ← this is the project slug, not the team slug
},
Suggested changes:
- Use
team.teamId
for the team’s ID - Use
params.team_slug
for the team’s slug
Example diff:
- projectMeta: {
- projectSlug: params.project_slug,
- teamId: team.id,
- teamSlug: team.slug,
- },
+ projectMeta: {
+ projectSlug: params.project_slug,
+ teamId: team.teamId,
+ teamSlug: params.team_slug,
+ },
Optionally, rename team
→ project
to make it clear you’re working with a project object.
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/analytics/page.tsx
around lines 22 to 25, the projectMeta object incorrectly uses team.id and
team.slug which actually refer to the project ID and slug, not the team. Fix
this by replacing team.id with project.teamId and team.slug with
params.team_slug. Optionally rename the variable from team to project for
clarity.
const team = await getProject(params.team_slug, params.project_slug); | ||
|
||
if (!team) { | ||
notFound(); | ||
} |
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.
🛠️ Refactor suggestion
Fix misleading variable name.
The variable is named team
but contains project data from getProject()
. This is confusing and could lead to maintenance issues.
- const team = await getProject(params.team_slug, params.project_slug);
+ const project = await getProject(params.team_slug, params.project_slug);
- if (!team) {
+ if (!project) {
notFound();
}
return (
<SharedNFTPage
params={{
contractAddress: params.contractAddress,
chainIdOrSlug: params.chainIdOrSlug,
projectMeta: {
projectSlug: params.project_slug,
- teamId: team.id,
- teamSlug: team.slug,
+ teamId: project.id,
+ teamSlug: project.slug,
},
}}
/>
);
Also applies to: 22-25
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx
around lines 10-14 and 22-25, the variable named `team` actually holds project
data returned from `getProject()`, which is misleading. Rename the variable from
`team` to `project` or another appropriate name that reflects it contains
project data to improve code clarity and maintainability.
params: Promise<ProjectContractPageParams>; | ||
}) { | ||
const params = await props.params; | ||
const team = await getProject(params.team_slug, params.project_slug); |
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.
Inconsistent API usage and confusing variable naming.
The variable is named team
but you're calling getProject(params.team_slug, params.project_slug)
which should return a Project
object, not a Team
. This is inconsistent with other similar pages (settings/account) that use getTeamBySlug
.
- const team = await getProject(params.team_slug, params.project_slug);
+ const project = await getProject(params.team_slug, params.project_slug);
Or if you need team data specifically:
- const team = await getProject(params.team_slug, params.project_slug);
+ const team = await getTeamBySlug(params.team_slug);
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/permissions/page.tsx
at line 10, the variable named 'team' is assigned the result of getProject,
which returns a Project object, causing confusion and inconsistency. Rename the
variable to 'project' to reflect its actual content, or if team data is needed,
replace the call with getTeamBySlug(params.team_slug) to retrieve the Team
object. Ensure variable names and API calls align with the data they represent
for clarity and consistency.
import { getClientThirdwebClient } from "@/constants/thirdweb-client.client"; | ||
import { redirect } from "next/navigation"; |
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.
Avoid invoking code from .client
modules inside a Server Component
getClientThirdwebClient
is imported from a file that (by convention) ends with .client
.
If that file contains the "use client"
directive, Webpack will treat it as a client-only bundle.
Calling a function from a client module inside a Server component violates RSC rules and
will throw during build:
Module "...thirdweb-client.client" is a client module, but
its default export is used in a server component.
Move the helper to a neutral/server file or wrap the call in a dedicated client component:
- import { getClientThirdwebClient } from "@/constants/thirdweb-client.client";
+ // 1. create thirdweb-client.server.ts (no "use client")
+ // 2. re-export/get the server-safe helper from there
+ import { getClientThirdwebClient } from "@/constants/thirdweb-client.server";
Also applies to: 56-60
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/layout.tsx
around lines 4-5 and 56-60, the import and usage of getClientThirdwebClient from
a `.client` module violates React Server Component rules because client modules
cannot be used directly in server components. To fix this, move the
getClientThirdwebClient helper function to a neutral or server-only file without
the "use client" directive, or alternatively, wrap the code that calls this
function inside a dedicated client component so that the server component does
not directly invoke client-only code.
const teamsAndProjects = await Promise.all( | ||
teams.map(async (team) => ({ | ||
team, | ||
projects: await getProjects(team.slug), | ||
})), | ||
); | ||
|
||
const project = teamsAndProjects | ||
.find((t) => t.team.slug === decodeURIComponent(params.team_slug)) | ||
?.projects.find((p) => p.slug === params.project_slug); | ||
|
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.
🛠️ Refactor suggestion
N + 1 fetch pattern – fetch only the current team’s projects
You currently fetch projects for every team, but immediately discard all
except the one matching params.team_slug
.
On organisations with many teams this adds unnecessary latency and load.
-const teamsAndProjects = await Promise.all(
- teams.map(async (team) => ({
- team,
- projects: await getProjects(team.slug),
- })),
-);
-
-const project = teamsAndProjects
- .find((t) => t.team.slug === decodeURIComponent(params.team_slug))
- ?.projects.find((p) => p.slug === params.project_slug);
+const projects = await getProjects(team.slug);
+const project = projects.find((p) => p.slug === params.project_slug);
+
+const teamsAndProjects = [
+ { team, projects }, // keep existing consumer happy
+];
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/layout.tsx
around lines 40 to 50, the code fetches projects for all teams but only uses the
projects for the team matching params.team_slug, causing unnecessary data
fetching. Modify the code to first find the team matching params.team_slug, then
fetch projects only for that specific team to reduce latency and load.
if (!isERC20ClaimConditionsSupported && !isERC721ClaimConditionsSupported) { | ||
redirectToContractLandingPage({ | ||
chainIdOrSlug: params.chainIdOrSlug, | ||
contractAddress: params.contractAddress, | ||
projectMeta: params.projectMeta, | ||
}); | ||
} | ||
|
||
return ( | ||
<ClaimConditions | ||
contract={clientContract} | ||
isERC20={supportedERCs.isERC20} | ||
isLoggedIn={!!account} | ||
isMultiphase={true} | ||
/> |
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.
Potential runtime crash when supportedERCs
is undefined
If getContractPageMetadata
fails (network error or unsupported contract) the destructuring leaves supportedERCs === undefined
.
Subsequently accessing supportedERCs.isERC20
(line 68) will throw a TypeError and break the route.
Safest guard:
- if (!isERC20ClaimConditionsSupported && !isERC721ClaimConditionsSupported) {
+ if (
+ supportedERCs === undefined ||
+ (!isERC20ClaimConditionsSupported && !isERC721ClaimConditionsSupported)
+ ) {
redirectToContractLandingPage({ ... });
}
…and similarly gate the final render or provide a graceful error component.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if (!isERC20ClaimConditionsSupported && !isERC721ClaimConditionsSupported) { | |
redirectToContractLandingPage({ | |
chainIdOrSlug: params.chainIdOrSlug, | |
contractAddress: params.contractAddress, | |
projectMeta: params.projectMeta, | |
}); | |
} | |
return ( | |
<ClaimConditions | |
contract={clientContract} | |
isERC20={supportedERCs.isERC20} | |
isLoggedIn={!!account} | |
isMultiphase={true} | |
/> | |
if ( | |
supportedERCs === undefined || | |
(!isERC20ClaimConditionsSupported && !isERC721ClaimConditionsSupported) | |
) { | |
redirectToContractLandingPage({ | |
chainIdOrSlug: params.chainIdOrSlug, | |
contractAddress: params.contractAddress, | |
projectMeta: params.projectMeta, | |
}); | |
} | |
return ( | |
<ClaimConditions | |
contract={clientContract} | |
isERC20={supportedERCs.isERC20} | |
isLoggedIn={!!account} | |
isMultiphase={true} | |
/> |
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/shared-claim-conditions-page.tsx
around lines 57 to 71, the code accesses supportedERCs.isERC20 without checking
if supportedERCs is defined, which can cause a runtime crash if supportedERCs is
undefined. To fix this, add a guard to check if supportedERCs is defined before
accessing its properties and conditionally render the ClaimConditions component
or a fallback error UI to handle the undefined case gracefully.
contract={clientContract} | ||
isLoggedIn={!!account} | ||
projectMeta={undefined} // TODO | ||
/> | ||
); | ||
} |
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.
projectMeta
is lost when rendering the localhost client component
SharedClaimConditionsPage
passes projectMeta={undefined}
to ClaimConditionsClient
, which breaks deep-link construction inside that client component (e.g., redirects back to the overview page will miss the /team/:slug/:projectSlug/
prefix).
- projectMeta={undefined} // TODO
+ projectMeta={params.projectMeta}
Unless there is a compelling reason to drop the context on localhost, keep it consistent with the server-rendered path.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/shared-claim-conditions-page.tsx
around lines 50 to 55, the prop projectMeta is set to undefined when rendering
ClaimConditionsClient, causing loss of context needed for correct deep-link
construction. To fix this, pass the actual projectMeta value received by
SharedClaimConditionsPage down to ClaimConditionsClient instead of undefined,
ensuring consistent context between server and localhost client rendering.
) as unknown as AbiFunction; | ||
|
||
const moduleIndex = initializeFunction.inputs.findIndex( | ||
(i) => i.name === "_modules" || i.name === "modules", | ||
); | ||
|
||
modules = moduleIndex ? decodedData[moduleIndex] : undefined; | ||
} |
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.
Off-by-one bug causes modules list to be dropped when it is the first arg
findIndex
returns 0
when the matching parameter is the first in the _initialize
signature.
Because 0
is falsy, the ternary expression incorrectly treats it as “not found”, so modules
ends up as undefined
even though the argument was located.
-const moduleIndex = initializeFunction.inputs.findIndex(
- (i) => i.name === "_modules" || i.name === "modules",
-);
-modules = moduleIndex ? decodedData[moduleIndex] : undefined;
+const moduleIndex = initializeFunction.inputs.findIndex(
+ (i) => i.name === "_modules" || i.name === "modules",
+);
+modules = moduleIndex !== -1 ? decodedData[moduleIndex] : undefined;
This bug silently prevents module metadata from being fetched for many contracts.
Fixing it will surface the installed-module list as intended.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
) as unknown as AbiFunction; | |
const moduleIndex = initializeFunction.inputs.findIndex( | |
(i) => i.name === "_modules" || i.name === "modules", | |
); | |
modules = moduleIndex ? decodedData[moduleIndex] : undefined; | |
} | |
) as unknown as AbiFunction; | |
const moduleIndex = initializeFunction.inputs.findIndex( | |
(i) => i.name === "_modules" || i.name === "modules", | |
); | |
modules = moduleIndex !== -1 ? decodedData[moduleIndex] : undefined; | |
} |
🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/cross-chain/shared-cross-chain-page.tsx
around lines 229 to 236, the code uses a ternary check on moduleIndex which
fails when moduleIndex is 0 because 0 is falsy. Change the condition to
explicitly check if moduleIndex is not -1 (e.g., moduleIndex !== -1) before
accessing decodedData[moduleIndex] to correctly handle the case when the
matching parameter is the first argument.
PR-Codex overview
This PR primarily focuses on enhancing the handling of project-specific parameters within the contract-related pages of the application, allowing for better organization and navigation based on
teamSlug
andprojectSlug
.Detailed summary
teamSlug
andprojectSlug
props to various components and pages.ProjectContractPageParams
andProjectMeta
.teamSlug
andprojectSlug
in URLs.notFound
for missing teams or projects.Summary by CodeRabbit
New Features
Refactor
Bug Fixes
Chores